记录:OLLYDBG F2断点 F7 F8单步 F9快速运行
目标程序:
静态分析
工具IDA
涉及序列号等判断的主体函数的主要部分:
通过if else即条件判断,长度小于5时会弹窗的一个字符串为用户名,即String
因此String1为序列号
v5 = GetDlgItemTextA(hWnd, 110, &String, 81);//返回值v5是返回字符串的长度
GetDlgItemTextA(hWnd, 1000, &String1, 101);
if ( String && v5 >= 5 )
{
if ( sub_401340(&String1, &String, v5) )//分析1
{
lstrcpyA(::String1, String2);
v6 = GetDlgItem(hWnd, 110);
EnableWindow(v6, 0);
v7 = GetDlgItem(hWnd, 1000);
EnableWindow(v7, 0);
v8 = GetDlgItem(hWnd, 1000);
}
else
{
lstrcpyA(::String1, &v17);
v8 = GetDlgItem(hWnd, 1000);
}
}
else //通过该else判断,v5<5的会弹出窗口,手动测试程序,获得String为用户名
{
lstrcpyA(::String1, &v15);
v8 = GetDlgItem(hWnd, 110);
}
SetFocus(v8);
MessageBeep(0);
DialogBoxParamA(hInstance, (LPCSTR)0x79, hWnd, sub_401060, 0);
关键函数——分析1:
BOOL __cdecl sub_401340(LPCSTR lpString1, LPSTR a2, int a3)
{//a2:用户名; lpString1:输入的序列号; a3:v5即用户名长度
int v3; // ecx@1
int v4; // esi@1
signed int i; // eax@1
v3 = 3;
v4 = 0;
for ( i = 0; v3 < a3; ++i )
{
if ( i > 7 )
i = 0;
v4 += (unsigned __int8)byte_405030[i] * (unsigned __int8)a2[v3++];
//v4为关键,实现该计算逻辑即可获得序列号
}
wsprintfA(a2, aLd, v4);//将v4以ld的形式读取到a2
return lstrcmpA(lpString1, a2) == 0;//判断lpString1与序列号是否相同,此时a2是真正的序列号
}
解决:
- 静态分析通过v4逻辑手动或代码计算获得序列号
- 动态分析直接从寄存器查看序列号
v4逻辑:
byte数组的第i个值与a2的第v3个字符ascii值相乘得到一个值,这个值继续累加。v3从3开始,一直到a2末尾。
动态分析
OLLYDBG
关键函数:sub_401340==》相对偏移地址1340
OLLYDBG找到它
再很明显的看到wsprintfA函数,函数参数很明了:
在附近F2打断点,F9快速运行到那里
F8单步,看到了真实对应usr的序列号