首先吐槽一下红客训练营得到赛题居然没有pwn,只能去试试Reverse了
CrackMe
- 例行检查,无壳儿,32位程序
- 运行一下程序,看看大概的情况
- 32位ida打开,我想检索字符串FALSE,找到关键函数,但是好像在字符串窗口找不到,去rdata段(资源数据段,程序用到什么资源数据都在这里)和data段(这个段存放程序的全局数据、全局常量等)找找看,最后让我在rdata段找到了‘FALSE’
ctrl+x找到引用它的函数
int __thiscall sub_401730(CWnd *this)
{
int v2; // edi
HMODULE v3; // eax
int v4; // edx
struct CWnd *v5; // eax
int v6; // esi
int i; // eax
int v8; // eax
CWnd *v9; // eax
char v11[4]; // [esp+10h] [ebp-1D0h] BYREF
int v12; // [esp+14h] [ebp-1CCh]
int v13; // [esp+18h] [ebp-1C8h]
int v14; // [esp+1Ch] [ebp-1C4h] BYREF
int v15; // [esp+20h] [ebp-1C0h]
char v16[396]; // [esp+24h] [ebp-1BCh] BYREF
int v17[8]; // [esp+1B0h] [ebp-30h]
int v18; // [esp+1DCh] [ebp-4h]
v17[0] = 0xE; #初始化的数据
v17[1] = 0x28;
v17[2] = 0xC;
v17[3] = 0x39;
v17[4] = 6;
v17[5] = 5;
v17[6] = 0x20;
v17[7] = 0x1F;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v14);
v2 = 0;
v18 = 0;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(v11);
LOBYTE(v18) = 1;
v3 = GetModuleHandleW(0);
v4 = *((unsigned __int8 *)v3 + 1);
v12 = *(_BYTE *)v3;
v13 = v4;
CWnd::UpdateData(this, 1);
v5 = CWnd::GetDlgItem(this, 1000);
CWnd::GetWindowTextW(v5);
v6 = *(_DWORD *)(v14 - 12);
v15 = 0;
memset(v16, 0, sizeof(v16));
if ( v6 > 0 )
{
do
{
*(&v15 + v2) = (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v14, v2);
++v2;
}
while ( v2 < v6 );
}
for ( i = 0; i < v6; ++i )
{
if ( (i & 1) != 0 )
*(&v15 + i) ^= v13;
else
*(&v15 + i) ^= v12;
}
v8 = 0;
if ( v6 <= 0 )
goto LABEL_14;
do
{
if ( *(&v15 + v8) != v17[v8] )
break;
++v8;
}
while ( v8 < v6 );
if ( v8 == 8 && v6 == 8 )
{
MessageBoxW(0, L"TRUE", &Caption, 0);
}
else
{
LABEL_14:
MessageBoxW(0, L"FALSE", &word_4037A8, 0);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator=(&v14, &unk_4037C0);
v9 = CWnd::GetDlgItem(this, 1000);
CWnd::SetWindowTextW(v9);
}
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(v11);
return ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v14);
}
大概就是一开始给我们初始化了一个数据,计算一下i&1,发现然是错位跟v13和v12进行异或操作,所以说这题的主要逻辑是将我们输入的数据错位跟v13和v12进行异或操作,最后得到初始化的那个数组。只要将初始化的那个数组跟v13还有v12异或一下,就能得到正确的输入值
v13和v12的值来自这里
v3 = GetModuleHandleW(0);
v4 = *((unsigned __int8 *)v3 + 1);
v12 = *(_BYTE *)v3;
v13 = v4;
百度百科关于GetModuleHandleW(0)函数的解释,看字面意思没太理解,当时就卡在这里了,用od调试了半天,没找到v13和v12的值
比赛结束后用ida调试,根据初始化数组的长度为8,所以我们输入的数据长度也是8,动调的时候随便输入长度为8的字符串即可
找到了他们的值,赋值语句主要在这边,在locals窗口找到了v12和v13
得到了v12和v13的值,就可以写个脚本算一下正确的注册码了
a=[0x0e,0x28,0x0c,0x39,6,5,0x20,0x1f]
v12=0x4d
v13=0x5a
string=""
for i in range(8):
if (i&1)!=0:
string+=chr(a[i]^v13)
else:
string+=chr(a[i]^v12)
print(string)
应该是由于我不熟悉汇编,所以相比od,ida我用的更顺手些。
Antidebug
- 例行检查,32位程序,无壳儿
- 运行一下程序,看看大概的情况
- 由于是对话框的输入,首先用Resource Hacker来寻找一下输入框的位置,看到key的控件标识是1000
在ida中alt+i,调出搜索立即数框,搜索1000
找到调用的地方
双击来到关键函数处,发现有jz 和 jnz跳转到相同位置,初步怀疑这里有花指令影响了ida的正常运行,nop(key path -> Fill range ,pathc为nop)掉
他们跳转到的local_401524,注意 00401524是个多字节指令,先使用快捷键d转为数据,然后将它nop掉,再将后边的使用快捷键c转为代码
修改后如图
在找到函数开始的位置push ebp的地方,右键 create function,然后就能f5查看伪代码了
逻辑很简单,当输入的值等于2882395322的时候提示正确
这题主要是考察了一个去花指令