阿虚
Hello World!
Hello World!
独树一帜

0x0

——————–

环境:

系统:Windows 10

工具:IDA 7.X

——————–

0x1

程序界面如下, 要求输入账号CTFHUB得到正确的解码。随便输入Code点击Check并没有任何反应。

http://www.xuwu.org/wp-content/uploads/2020/02/dsyz1.png

0x2

将EXE载入IDA中查看导入表搜索“MessageBox”,有使用MessageBoxA来进行弹框并且只有一处地方使用了MessageBoxA。且附近有使用GetDlgItemTextA函数。MessageBoxA的对话框消息又是字符串“GOOD JOB! – CRACKED!”。

http://www.xuwu.org/wp-content/uploads/2020/02/dsyz2.png

通过图形显示反汇编只要sub_401000函数返回值为1则注册成功。sub_401000函数支持两个char*参数,参数是GetDlgItemTextA获取到的字符串。

http://www.xuwu.org/wp-content/uploads/2020/02/dsyz3-1024x541.png

0x3

.text:00401000 check           proc near               ; CODE XREF: DialogFunc+97↓p
.text:00401000
.text:00401000 user            = dword ptr  4
.text:00401000 password        = dword ptr  8
.text:00401000
.text:00401000                 push    ebx
.text:00401001                 mov     ebx, [esp+4+password]
.text:00401005                 push    ebp
.text:00401006                 push    esi
.text:00401007                 mov     esi, [esp+0Ch+user]
.text:0040100B                 mov     cl, [ebx]
.text:0040100D                 xor     ebp, ebp
.text:0040100F                 push    edi
.text:00401010                 mov     al, [esi]
.text:00401012                 cmp     al, cl
.text:00401014                 jnz     ret             
.text:0040101A                 mov     edi, esi
.text:0040101C                 or      ecx, 0FFFFFFFFh
.text:0040101F                 xor     eax, eax
.text:00401021                 repne scasb
.text:00401023                 not     ecx
.text:00401025                 dec     ecx
.text:00401026                 cmp     ecx, 5
.text:00401029                 jb      ret             ; 判断user的长度,小于5就跳出
.text:0040102F                 cmp     byte ptr [ebx+1], 2Dh ; '-'
.text:00401033                 jnz     ret             ; password[2] != '-' 就跳出
.text:00401039                 mov     edi, esi
.text:0040103B                 or      ecx, 0FFFFFFFFh
.text:0040103E                 xor     eax, eax
.text:00401040                 xor     edx, edx
.text:00401042                 repne scasb
.text:00401044                 not     ecx
.text:00401046                 dec     ecx
.text:00401047                 jz      short loc_401060 ; 再次获取user的长度,等于0就跳出
.text:00401049 loc_401049:                             ; CODE XREF: check+5E↓j
.text:00401049                 movsx   ecx, byte ptr [edx+esi]
.text:0040104D                 add     ebp, ecx        ; 累加user的字符和
.text:0040104F                 mov     edi, esi
.text:00401051                 or      ecx, 0FFFFFFFFh
.text:00401054                 xor     eax, eax
.text:00401056                 inc     edx
.text:00401057                 repne scasb
.text:00401059                 not     ecx
.text:0040105B                 dec     ecx
.text:0040105C                 cmp     edx, ecx
.text:0040105E                 jb      short loc_401049 ; 循环累加user的ascii字符和
.text:00401060 loc_401060:                             ; CODE XREF: check+47↑j
.text:00401060                 add     ebp, 6064h      ; user的和在加0x606h
.text:00401066                 push    ebp
.text:00401067                 push    offset Format   ; "%lu"
.text:0040106C                 push    offset Buffer   ; Buffer
.text:00401071                 call    _sprintf        
.text:00401076                 mov     dl, [esi]
.text:00401078                 mov     edi, esi
.text:0040107A                 or      ecx, 0FFFFFFFFh
.text:0040107D                 xor     eax, eax
.text:0040107F                 mov     user_0_, dl
.text:00401085                 mov     user_1_, 2Dh ; '-'
.text:0040108C                 repne scasb
.text:0040108E                 not     ecx
.text:00401090                 dec     ecx             
.text:00401091                 movsx   eax, byte ptr [ecx+esi-1]
.text:00401096                 push    eax             ; C
.text:00401097                 call    _toupper
.text:0040109C                 mov     user_1_+1, al   ; 将USER最后一个字符转换为大写字符
.text:004010A1                 mov     edi, offset Buffer
.text:004010A6                 or      ecx, 0FFFFFFFFh
.text:004010A9                 xor     eax, eax
.text:004010AB                 repne scasb
.text:004010AD                 not     ecx
.text:004010AF                 sub     edi, ecx        ; 得到Buffer的长度
.text:004010B1                 add     ebp, 6064h      ; user的和在加0x606h
.text:004010B7                 mov     esi, edi
.text:004010B9                 mov     edx, ecx
.text:004010BB                 mov     edi, offset user_0_
.text:004010C0                 or      ecx, 0FFFFFFFFh
.text:004010C3                 repne scasb             ; 这个scasb是将user_0_地址移动到字符串尾部
.text:004010C5                 mov     ecx, edx
.text:004010C7                 dec     edi             ; 指针指向user_0_'0'处
.text:004010C8                 shr     ecx, 2
.text:004010CB                 rep movsd               ; 做4字节拷贝,将Buffer拷贝到user_0_尾部
.text:004010CD                 mov     ecx, edx
.text:004010CF                 push    ebp
.text:004010D0                 and     ecx, 3
.text:004010D3                 push    offset Format   ; "%lu"
.text:004010D8                 rep movsb               ; 将Buffer最后几个字节拷贝到user_0_尾部
.text:004010DA                 mov     edi, offset unk_406030
.text:004010DF                 or      ecx, 0FFFFFFFFh
.text:004010E2                 repne scasb
.text:004010E4                 not     ecx
.text:004010E6                 sub     edi, ecx        ; 计算unk_406030的长度
.text:004010E8                 push    offset Buffer   ; Buffer
.text:004010ED                 mov     esi, edi
.text:004010EF                 mov     edx, ecx        
.text:004010F1                 mov     edi, offset user_0_
.text:004010F6                 or      ecx, 0FFFFFFFFh
.text:004010F9                 repne scasb
.text:004010FB                 mov     ecx, edx
.text:004010FD                 dec     edi
.text:004010FE                 shr     ecx, 2
.text:00401101                 rep movsd
.text:00401103                 mov     ecx, edx
.text:00401105                 and     ecx, 3
.text:00401108                 rep movsb               ; unk_406030字符串拼接到user_0_尾部
.text:0040110A                 call    _sprintf        ; Buffer重新打印新的user_sum
.text:0040110F                 mov     edi, offset Buffer
.text:00401114                 or      ecx, 0FFFFFFFFh
.text:00401117                 xor     eax, eax
.text:00401119                 add     esp, 1Ch
.text:0040111C                 repne scasb
.text:0040111E                 not     ecx
.text:00401120                 sub     edi, ecx        ; 计算Buffer的长度
.text:00401122                 mov     esi, edi
.text:00401124                 mov     edx, ecx
.text:00401126                 mov     edi, offset user_0_
.text:0040112B                 or      ecx, 0FFFFFFFFh
.text:0040112E                 repne scasb
.text:00401130                 mov     ecx, edx
.text:00401132                 dec     edi
.text:00401133                 shr     ecx, 2
.text:00401136                 rep movsd
.text:00401138                 mov     ecx, edx
.text:0040113A                 mov     eax, ebx
.text:0040113C                 and     ecx, 3
.text:0040113F                 rep movsb               ; 将新的Buffer拷贝到User_0_的尾部
.text:00401141                 mov     esi, offset user_0_
.text:00401146 do_while:                               ; CODE XREF: check+168↓j
.text:00401146                 mov     dl, [eax]       ; eax = password
.text:00401148                 mov     bl, [esi]       ; esi = user_0_
.text:0040114A                 mov     cl, dl
.text:0040114C                 cmp     dl, bl
.text:0040114E                 jnz     short loc_401175 ; if (*user_0_ != *password)
.text:0040114E                                         ;     jmp loc_401175;
.text:00401150                 test    cl, cl
.text:00401152                 jz      short ret_ok    ; if (*pasword == '\0')
.text:00401152                                         ;     jmp loc_40116A;
.text:00401154                 mov     dl, [eax+1]
.text:00401157                 mov     bl, [esi+1]
.text:0040115A                 mov     cl, dl
.text:0040115C                 cmp     dl, bl
.text:0040115E                 jnz     short loc_401175 ; if (*(user_0_ + 1) != *(password + 1))
.text:0040115E                                         ;     jmp loc_401175;
.text:00401160                 add     eax, 2          ; password += 2;
.text:00401163                 add     esi, 2          ; user_0_ += 2;
.text:00401166                 test    cl, cl
.text:00401168                 jnz     short do_while  ; ; if (*pasword == '\0')
.text:00401168                                         ;     jmp loc_00401146;
.text:0040116A ret_ok:                                 ; CODE XREF: check+152↑j
.text:0040116A                 xor     eax, eax
.text:0040116C                 xor     edx, edx
.text:0040116E                 test    eax, eax
.text:00401170                 setz    dl
.text:00401173                 jmp     short ret_end
.text:00401175 loc_401175:                             ; CODE XREF: check+14E↑j
.text:00401175                 sbb     eax, eax
.text:00401177                 sbb     eax, 0FFFFFFFFh
.text:0040117A                 xor     edx, edx
.text:0040117C                 test    eax, eax
.text:0040117E                 setz    dl
.text:00401181                 jmp     short ret_end
.text:00401183 ret:                                    ; CODE XREF: check+14↑j
.text:00401183                 mov     edx, [esp+10h+user]
.text:00401187 ret_end:                                ; CODE XREF: check+173↑j
.text:00401187                 mov     ecx, 40h ; '@'
.text:0040118C                 xor     eax, eax
.text:0040118E                 mov     edi, offset user_0_
.text:00401193                 rep stosd
.text:00401195                 pop     edi
.text:00401196                 pop     esi
.text:00401197                 pop     ebp
.text:00401198                 mov     eax, edx
.text:0040119A                 pop     ebx
.text:0040119B                 retn
.text:0040119B check           endp

0x4

通过分析反汇编可以知道,Code开头规则:

  1. Name的长度必须大于5。
  2. Code第一个字符必须是Name的第一个字符的大写。
  3. Code第二个字符一定是‘-’。
  4. Code第三个字符一定是Name最后一个字符的大写
  5. Code后续拼接Name字符累加和在加上常量0x6064的整形字符串。
  6. Code继续拼接字符‘-’
  7. Code继续5再次累加0x6064的整形字符串。

0x5

#include <iostream>
#include <stdlib.h>
#include <windows.h>

bool check(char* user, char* password)
{
    int len = strlen(user);
    if (len < 5)
    {
        return false;
    }

    if (password[1] != '-')
    {
        return false;
    }

    char key[256] = { 0x0 };
    key[0] = (char)toupper(user[0]);
    key[1] = '-';
    key[2] = (char)toupper(user[len-1]);

    DWORD sum = 0;
    for (int i = 0; i < len; i++)
    {
        sum += user[i];
    }
    sum += 0x6064;

    char buf[256] = { 0x0 };
    sprintf_s(buf, "%lu", sum);

    strcat_s(key, buf);
    strcat_s(key, "-");

    sum += 0x6064;
    sprintf_s(buf, "%lu", sum);
    strcat_s(key, buf);

    if (strcmp(password, key) == 0)
    {
        return true;
    }

    return false;
}


int main()
{
    char name[256] = { 0x0 };
    char password[256] = { 0x0 };

    std::cout << "in name: \n";
    std::cin >> name; 

    std::cout << "in password: \n";
    std::cin >> password;

    if (check(name, password))
    {
        std::cout << "ok \n";
    }

    return 0;
}

阿虚

文章作者

发表评论

textsms
account_circle
email

Hello World!

独树一帜
0x0 -------------------- 环境: 系统:Windows 10 工具:IDA 7.X -------------------- 0x1 程序界面如下, 要求输入账号CTFHUB得到正确的解码。随便输入Code点…
扫描二维码继续阅读
2020-02-18