WinSnap是一款屏幕截图软件,可以方便地对屏幕截图并可进行处理。其下载地址是:
http://www.ntwind.com/software/winsnap.html
其最新版为3.10,未注册版本只有30天使用期。
一. 程序分析
首先用PEID查一下是否加壳,显示“什么也没发现”。
既然不知道有没有壳,那就直接载入OD分析,使用通用的方法对GetDlgItemTextW下断即可很容易获取输入的用户名和序列号。然后就是字符转换函数,将用户名和序列号由Unicode转换为ASCII。
再走几步就到了对用户注册合法性校验的函数,地址为0x00409A10,下面用IDA载入程序对这个函数进行静态分析。
此函数非常庞大,下面分几部分进行说明。
首先,函数开始部分将用户名转换为大写,紧接着就是对用户名进行处理。
我们可以看到首先就是对sub_409790函数的调用,传递的参数是用于处理用户名缓冲区和-1。
此函数在用户名处理的过程中被多次调用。
.text:00409790 sub_409790 proc near ; CODE XREF: CheckPas+75p
.text:00409790 ; CheckPas+1D2p
.text:00409790
.text:00409790 var_104 = byte ptr -104h
.text:00409790 var_4 = dword ptr -4
.text:00409790 pUserNameBuf = dword ptr 4
.text:00409790 arg_4 = dword ptr 8
.text:00409790
.text:00409790 sub esp, 104h
.text:00409796 mov eax, dword_44F050
.text:0040979B xor eax, esp
.text:0040979D mov [esp+104h+var_4], eax
.text:004097A4 mov eax, [esp+104h+arg_4] ; 参数2:-1
.text:004097AB push ebx
.text:004097AC push ebp
.text:004097AD mov ebp, [esp+10Ch+pUserNameBuf]
.text:004097B4 push esi
.text:004097B5 push edi
.text:004097B6 mov edi, ebp ; edi 用户名指针
.text:004097B8 test eax, eax
.text:004097BA jge short loc_4097CA
.text:004097BC mov eax, ebp
.text:004097BE lea edx, [eax+1]
.text:004097C1
.text:004097C1 loc_4097C1: ; CODE XREF: sub_409790+36j
.text:004097C1 mov cl, [eax]
.text:004097C3 inc eax
.text:004097C4 test cl, cl
.text:004097C6 jnz short loc_4097C1
.text:004097C8 sub eax, edx ; 计算用户名长度
.text:004097CA
.text:004097CA loc_4097CA: ; CODE XREF: sub_409790+2Aj
.text:004097CA xor edx, edx ; 数组索引变量
.text:004097CC mov esi, eax ; esi 用户名长度
.text:004097CE mov edi, edi ; edi 用户名指针
.text:004097D0
.text:004097D0 loc_4097D0: ; CODE XREF: sub_409790+70j
.text:004097D0 mov bl, dl
.text:004097D2 add bl, 0Dh
.text:004097D5 mov byte_457B78[edx], dl
.text:004097DB mov [esp+edx+114h+var_104], bl
.text:004097DF test eax, eax
.text:004097E1 jle short loc_4097F9
.text:004097E3 mov cl, [edi]
.text:004097E5 add cl, al
.text:004097E7 xor cl, bl
.text:004097E9 sub esi, 1
.text:004097EC mov [esp+edx+114h+var_104], cl ; 存放经过处理的用户名的局部数组
.text:004097F0 jnz short loc_4097F8
.text:004097F2 mov edi, ebp
.text:004097F4 mov esi, eax
.text:004097F6 jmp short loc_4097F9
.text:004097F8 ; ---------------------------------------------------------------------------
.text:004097F8
.text:004097F8 loc_4097F8: ; CODE XREF: sub_409790+60j
.text:004097F8 inc edi
.text:004097F9
.text:004097F9 loc_4097F9: ; CODE XREF: sub_409790+51j
.text:004097F9 ; sub_409790+66j
.text:004097F9 inc edx
.text:004097FA cmp edx, 100h
.text:00409800 jl short loc_4097D0
.text:00409802 xor eax, eax
.text:00409804 xor ecx, ecx ;
.text:00409806 mov dword_457C78, eax
.text:0040980B mov dword_457C7C, eax
.text:00409810
.text:00409810 loc_409810: ; CODE XREF: sub_409790+B2j
.text:00409810 mov dl, byte_457B78[eax]
.text:00409816 movzx esi, [esp+eax+114h+var_104]
.text:0040981B movzx edi, dl
.text:0040981E add esi, ecx
.text:00409820 add edi, esi
.text:00409822 and edi, 0FFh
.text:00409828 mov ecx, edi
.text:0040982A mov bl, byte_457B78[ecx]
.text:00409830 mov byte_457B78[eax], bl
.text:00409836 inc eax
.text:00409837 cmp eax, 100h
.text:0040983C mov byte_457B78[ecx], dl
.text:00409842 jl short loc_409810
.text:00409844 mov ecx, [esp+114h+var_4]
.text:0040984B pop edi
.text:0040984C pop esi
.text:0040984D pop ebp
.text:0040984E pop ebx
.text:0040984F xor ecx, esp
.text:00409851 call sub_4322D2
.text:00409856 add esp, 104h
.text:0040985C retn
.text:0040985C sub_409790 endp
以上代码将处理后的用户名存放在大小为100h字节的UserNameBuf中,
其中,主要运算过程是根据UserNameBuf的值进行运算后建立一个100h字节的局部变量,接着根据局部数组
的值对457B78中的元素进行运算,用运算后的结构作为索引457B78数组的值进行两两置换,也就是矩阵的运算。
现给出它的伪代码。
void sub_409790(void pasbuf, int par2)
{
BYTE buf[0x100];
void pUserNameBuf = pasbuf;
DWORD len = par2;
if(par2 < 0)
len = GetLen(pUserNameBuf);
DWORD temp = len;
DWORD index = 0;
while(index < 0x100)
{
bl = (BYTE)index + 0xD;
457B78[index] = (BYTE)index;
buf[index] = bl;
if(len > 0)
{
// 根据用户名缓冲区运算后对局部数组赋值
buf[index] = (*pUserNameBuf + (BYTE)len) ^ bl;
temp--;
if(temp != 0)
pUserNameBuf++;
else {
pUserNameBuf = par1;
temp = len;
}
}
index++;
}
[457C78] = 0;
[457C7C] = 0;
index = 0;
temp2 = 0;
while(index < 0x100)
{
// 根据buf的值对索引进行运算,然后置换索引对应的值
dl = 457B78[index];
temp2 = ((DWORD)dl + (DWORD)buf[index] + temp2) ^ 0xFF;
457B78[index] = temp2;
457B78[temp2] = dl;
index++;
}
}
409790(UserNameBuf, -1);
DWORD num = 0x100;
while(num != 0)
{
var1 = [457C7C]; //eax
index1 = [457C78]; //esi
num2 = 0;
while(num2 < 0x100)
{
for(int i=0; i<4; i++)
{
var1 = var1++ & 0xFF;
temp = 457B78[var1];
index1 = (temp + index1) & 0xFF;
457B78[var1] = 457B78[index1];
457B78[index1] = temp;
index2 = (temp + 457B78[var1]) & 0xFF;
UserNameBuf[num2 + i] = 457B78[index2];
}
num2 += 4;
}
[457C7C] = var1;
[457C78] = index1;
sub_409790(UserNameBuf, 0x100);
num--;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课