首页
社区
课程
招聘
[原创]Crackme - Acid burn初识逆向
发表于: 2023-8-19 16:45 10522

[原创]Crackme - Acid burn初识逆向

2023-8-19 16:45
10522

双击运行,弹出对话框,猜测是MessageBox

点击确定,弹出主对话框

点击Serial/Name,提示输入用户名和序列号

随机输入,弹出提示对话框,提示序列号错误。猜测提示对话框是通过MessageBox调用。

通过首次运行中,推测点击Check it Baby!后弹出的对话框是通过MessageBox调用的,所以打开OD加载可执行文件,ALT+E 查看可执行模块。

找到主模块右键查看名称,即可查看到主模块中调用的函数。

搜索MessageBox,并在每个参考上设置断点。

Alt + b 查看所有断点。F9运行程序。

通过函数入参可以看出是首次运行时弹出的第一个对话框。按F9再次执行,首个对话框弹出。

点击Serial/Name,随机输入用户名和序列号,点击Check it Baby!,再次停在MessageBox断点处。通过函数入参,可以发现是检验用户名和序列号后弹出的对话框文本。

在栈中查看函数返回地址,返回调用函数,右键 --> 反汇编窗口中跟随

向上查看汇编指令,可以看到MessageBox的文本参数。jnz short 0042FB1F是关键跳,表示结果不相等则跳转到0042FB1F处。

将关键跳使用nop填充后运行,随机输入用户名和序列号,发现验证成功,该方法是爆破。

在上面几个call下断点,逐个分析,发现疑似序列号文本。


输入用户名和对应的序列号发现验证成功。

在栈中 EBP-4,EBP-8,EBP-18的数据,分别是序列号的三部分,通过反汇编窗口0x0042FAC5内存位置可以看出获取了EBP-18内存地址。在此处下断点重新运行。

单步调试可以发现,代码逻辑是先获取EBP-18的内存地址赋值到edx寄存器,然后取内存地址为0x00431750的四个字节内容赋值到eax寄存器。

单步步过0x0042FACD内存地址处call。查看栈EBP-18位置,序列号第二部分4018被赋值到EBP-18位置。也就是说内存地址为0x00431750的值0x0FB2经过了0x0042FACD内存地址处call计算得出4018。其实就是做了进制转换,将十六进制转换成了十进制。

那么就需要知道内存地址为0x00431750是什么时候得到此值的,看上面的汇编指令。在0x0042FA87内存地址处下断点,重新运行。可以发现0x00431750现在值为0x29

单步运行,将我们输入的用户名字符串地址赋值给寄存器eax,然后取用户名第一个字节(ASCII码)乘0x29,将结果乘2,最后 赋值回0x00431750

0x29是固定值,所以整体算法逻辑就是,0x00431750 = 取用户名第一个字节 * 0x29 * 2,将0x00431750取四个字节十六进制转换成十进制,就得到了序列号第二部分,最后拼接字符串CW-XXX-CRACKED。

刚刚接触逆向的小白,编程能力还有待提升,记录一下学习过程。欢迎大佬给予意见,感谢。目标程序已上传附件。

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    while (true)
    {
        printf("请输入用户名:");
        string szName;
        cin >> szName;
 
        if (szName.size() < 4)
        {
            printf("用户名长度小于4,请重新输入!\r\n");
            continue;
        }
 
        unsigned int nTmp = 0x29;
        //取第一个字节
        unsigned int nFirst = szName[0];
 
        unsigned int nSecondRes = nTmp * nFirst * 2;
 
        char szSecond[255] = {};
        itoa(nSecondRes, szSecond, 10);
 
        string szFirst = { "CW-" };
 
        string szFinal = { "-CRACKED" };
 
        string szSerialNumber;
 
         
        szSerialNumber.append(szFirst).append(szSecond).append(szFinal);
 
        printf("序列号为:%s\r\n", szSerialNumber.c_str());
    }
     
    return 0;
}
#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    while (true)
    {
        printf("请输入用户名:");
        string szName;
        cin >> szName;
 
        if (szName.size() < 4)
        {
            printf("用户名长度小于4,请重新输入!\r\n");
            continue;
        }
 
        unsigned int nTmp = 0x29;
        //取第一个字节
        unsigned int nFirst = szName[0];
 
        unsigned int nSecondRes = nTmp * nFirst * 2;
 
        char szSecond[255] = {};
        itoa(nSecondRes, szSecond, 10);
 
        string szFirst = { "CW-" };
 
        string szFinal = { "-CRACKED" };
 
        string szSerialNumber;
 
         
        szSerialNumber.append(szFirst).append(szSecond).append(szFinal);
 
        printf("序列号为:%s\r\n", szSerialNumber.c_str());
    }
     
    return 0;
}
.586
.model flat,stdcall
option casemap:none
 
   include windows.inc
   include user32.inc
   include kernel32.inc
   include Resource.inc
   include msvcrt.inc
    
   includelib user32.lib
   includelib kernel32.lib
   includelib msvcrt.lib
 
WinMain proto :DWORD
 
 
.data
 
g_szUserName db 256 dup(0)
g_szErrorInfo db "用户名个数小于4,请重新输入",0
g_nBase dd 0
g_szFirst db "CW-",0
g_szFinal db "-CRACKED",0
g_szSecond db 256 dup (0)
g_szTmp db "%d",0
g_szResult db 256 dup (0)
 
.code
 
;对话过程函数
DlgProc proc hWnd:HWND,nMsg:UINT,wParam:WPARAM,lParam:LPARAM
     
     
    .IF nMsg == WM_COMMAND
        mov eax,wParam
        .IF ax == IDB_GENERATE
             
            ;获取用户名编辑框中的文本
            invoke GetDlgItemText,hWnd,IDE_NAME,offset g_szUserName,255
            .IF eax < 4
                invoke MessageBox,NULL,offset g_szErrorInfo,NULL,MB_OK
                mov eax,FALSE
                ret
            .ENDIF
            ;取用户名文本首字节
            movzx eax,byte ptr [g_szUserName]
            mov dword ptr [g_nBase],29h
             
            imul dword ptr [g_nBase]
            mov dword ptr[g_nBase],eax
            mov eax,dword ptr[g_nBase]
            add dword ptr[g_nBase],eax
             
            invoke crt_sprintf,offset g_szSecond,offset g_szTmp,dword ptr[g_nBase]
            invoke crt_strcat,offset g_szResult,offset g_szFirst
            invoke crt_strcat,offset g_szResult,offset g_szSecond
            invoke crt_strcat,offset g_szResult,offset g_szFinal
            ;设置序列号
            invoke SetDlgItemText,hWnd,IDE_SERIAL,offset g_szResult
            ;清空序列号
            mov  byte ptr [g_szResult],0
        .ELSEIF ax == IDB_CANCEL
            invoke EndDialog,hWnd,0
            mov eax,FALSE
            ret
        .ENDIF
         
         
    .ELSEIF nMsg == WM_CLOSE
        invoke EndDialog,hWnd,0
    .ENDIF
     
    mov eax,FALSE
    ret
DlgProc endp
 
WinMain proc hInst:HINSTANCE
    ;创建模态对话框
    invoke DialogBoxParam,hInst,IDD_DLG1,NULL,offset DlgProc,0
     
     
    ret
WinMain endp
 
 
;程序入口点
start:
    invoke GetModuleHandle, NULL
    invoke WinMain,eax
    invoke ExitProcess,eax
 
 
end start
.586
.model flat,stdcall
option casemap:none
 
   include windows.inc
   include user32.inc
   include kernel32.inc
   include Resource.inc
   include msvcrt.inc
    
   includelib user32.lib
   includelib kernel32.lib
   includelib msvcrt.lib
 
WinMain proto :DWORD
 
 
.data
 
g_szUserName db 256 dup(0)
g_szErrorInfo db "用户名个数小于4,请重新输入",0
g_nBase dd 0
g_szFirst db "CW-",0
g_szFinal db "-CRACKED",0
g_szSecond db 256 dup (0)

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-8-29 21:08 被_Format编辑 ,原因:
上传的附件:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 2787
活跃值: (30801)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-8-19 20:17
2
雪    币: 27071
活跃值: (63057)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
3
建议 将目标程序上传论坛一份,方便其他人下载学习。
另外,若是涉及到代码展现,建议 尽量帖汇编代码文本上来,以代替图片。
2023-8-26 19:40
1
雪    币: 334
活跃值: (661)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
Editor 建议 将目标程序上传论坛一份,方便其他人下载学习。 另外,若是涉及到代码展现,建议 尽量帖汇编代码文本上来,以代替图片。
感谢您的建议,我会注意
2023-8-29 20:01
0
游客
登录 | 注册 方可回帖
返回
//