题目名称:skipper-64
所需工具:IDA Pro、Pwndbg、checksec
1、首先通过checksec检查保护模式:

代码中没有开启PIE(内存地址随机化)
2、将程序拖入到IDA PRO中,定位到main函数,F5反汇编
__int64 __fastcall main(int a1, char **a2, char **a3)
{
unsigned __int64 v3; // rsi
unsigned __int64 v4; // rdx
char s1; // [rsp+10h] [rbp-410h] BYREF
char v7; // [rsp+11h] [rbp-40Fh]
unsigned __int64 v8; // [rsp+418h] [rbp-8h]
v8 = __readfsqword(0x28u);
sub_400B3E(&s1, a2, a3); //创建子进程 执行uname 获取计算机名
printf("Computer name: %s\n", &s1);
if ( strcmp(&s1, "hax0rz!~") )//第一次判断
{
printf("Sorry, your computer's name - %s - is not correct!\n", &s1);
raise(9);
}
sub_400C4A(&s1); //读取内核版本号
printf("OS version: %s\n", &s1); //第二次判断
v3 = (unsigned __int64)"2.4.31";
if ( strcmp(&s1, "2.4.31") )
{
printf("Sorry, your OS version - %s - is not supported!\n", &s1);
v3 = (unsigned int)(v7 / v7 - 1);
v4 = (unsigned __int64)s1 >> 32;
LODWORD(v4) = s1 % (int)v3;
s1 /= (int)v3;
}
sub_400AC6(&s1, v3, v4); //查看电脑CPU型号
puts(&s1);
if ( strcmp(&s1, "AMDisbetter!") ) //第三次判断
{
printf("Sorry, your CPU - %s - is not supported!\n", &s1);
__asm { int 80h; LINUX - sys_exit }
JUMPOUT(0x40283BLL);
}
sub_400D5F();
return 0LL;
}
程序中进行了3次判断,同时创建了一个子进程执行uname
sub_400B3E(&s1, a2, a3); 函数中内部有一个fork函数专门用来创建子进程的。
所以我们调试的时候要只调试父进程即可。
3、怎么做呢?
首先程序中没有可利用的情况,其次我们电脑也很难满足3种条件,那么可以另辟蹊径!从strcmp判断函数上下手。
strcmp 比较函数,用来比较str1与str2是否一致,如果如果二者相同那么则将返回0,这个返回值存储在eax寄存器中。
所以到这里思路出现了:
通过动态调试,在每次执行完strcmp的时候手动将eax的值修改为0即通过对比。
4、实操
首先定位main函数地址![]()
我们在反汇编视图中找到main+1的区域
从这里开始向下寻找到我们的3个strcmp分别记录下来
![]()
第一个:0x40272F
第二个:0x402792
第三个:0x402810
然后回到PWNDBG中下断点执行
下断点方法 b *地址

然后输入set follow-fork-mode parent,防止之前的子进程干扰了调试导致的报错。
我们到达了第1个strcmp,再输入ni (下一步)执行这条命令,在执行后输入set $eax=0 将eax寄存器值设置为0
然后再次输入c(运行到下一个断点)
重复上面的步骤,直到完成了3个strcmp的时候再次输入c
最终得到flag

3043

被折叠的 条评论
为什么被折叠?



