1.查壳
发现是nsPack壳,这个脱壳的原理我不是很清楚,照着网上一步步做就成功了,具体细节以后再研究。
2.用OD脱壳
网上说的ESP定律什么的,下硬件断点,F5,来到这里
这个地方有点没搞清楚的是,OEP为什么在第一个JMP之后,也就是图中00401336
的位置。注意,下面的操作是错误的,我开始看到了push ebp
,就以为这是程序的入口点,再跟进一步,来到了下面的位置:
ok,看到了push ebp
,然后用od脱壳调试进程,结果不对。那么问题来了,如何确定程序的OEP呢?还有一个问题,在用OD脱壳调试进程时,重建输入表的选项,什么时候勾选什么时候不勾选呢?
3.找到算法
脱壳成功后,拖入IDA,直接进入int __cdecl main
处,F5查看伪代码。
这个算法不难。
nt __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // eax
char Buf; // [esp+4h] [ebp-38h]
char Dst; // [esp+5h] [ebp-37h]
Buf = 0;
memset(&Dst, 0, 0x31u);
printf("Please Input Flag:");
gets_s(&Buf, 0x2Cu);
//要求输入的字符串长度
if ( strlen(&Buf) == 42 )
{
v4 = 0;
//做了一个按位异或,可以知道关键的两个数据在byte_402130和dword_402150中
while ( (*(&Buf + v4) ^ byte_402130[v4 % 16]) == dword_402150[v4] )
{
if ( ++v4 >= 42 )
{
printf("right!\n");
goto LABEL_8;
}
}
printf("error!\n");
LABEL_8:
result = 0;
}
else
{
printf("error!\n");
result = -1;
}
return result;
}
查看两处关键的数据。
byte_402130
这个可以用上一篇文章中的py脚本,结果如下
dword_402150
的数据,这个我就有点没弄清,idapython读dword用哪个函数,如果还是用GetManyBytes
的话,是按照一个字节一个字节读取的。
这里就出现了问题,对于这些数据,判断在哪截至,有没有什么依据,这个题目我们知道它的长度是42,前面一个数据是字符串00截至,其他的题目也是这样判断的吗?
4.写解密程序
#include <iostream>
#include <string>
using namespace std;
int main()
{
//byte_402130
string str1 = "this_is_not_flag";
//dword_402150
int arr[] = {0x12,4, 8, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A, 0x10, 0x67, 0,0x41, 0,
1, 0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D,
0x40, 0x3E, 0x4B, 0x5F, 2, 1, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C,
0x16, 0x68, 0x5B, 0x12};
char results[50] ={0};
for (int i=0;i<42;i++)
{
//先将这两个数据都转成int类型,然后按位异或,最后的结果再转成字符串
results[i] = char(int(str1[i%16]) ^ arr[i]);
}
//输出结果
cout<<results;
system("pause");
return 0;
}
总结
脱壳还是不会!idapython里面常用的函数还有很多不清楚。