前几天,公司购买国外的某一软件狗过期了,但公司等着急用,
一时间老外又联系不上,只好先打狗临时用一下。随为菜鸟,
但作为公司唯一懂得一点破解的人,只好搞当仁不让了。
先拿过来用peid看看,有壳,"UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo",
呵呵,以前脱过,用UPX 通用脱壳机脱壳,运行脱壳后exe,跑起来了,说明脱壳成功,这样第一步过去了。
第二步,再用peid看看, "Microsoft Visual C++ 6.0",暗喜,这正是我比较熟悉的开发环境。
用OD装载,直接运行,出现不了运行主画面,看样子有反调试手段,然后运用OD 的HideOD插件,
所有选项钩上,再运行,还是不行。我是菜鸟,只好放弃OD了。
这样我只好祭起反汇编利器IDA。先介绍一下无狗时软件运行情况:启动时,弹出提示无狗,
运行后工具条中一关键按钮"Start"不见了。但可笑的是,这个软件菜单项"Start"还保留着,
只是点击无反应。菜单项"Start"保留对于我来说省了好多事,免得到时还要恢复菜单项,
工具条按钮就不要恢复了,有菜单项就行。
首先用资源编辑工具例如VC6打开资源,找到 菜单项"Start" 的COMMAND ID 为 0x8204,
根据VC的消息映射结构
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSig_vv, (AFX_PMSG)&memberFxn },
// ON_COMMAND(id, OnFoo) is the same as
// ON_CONTROL(0, id, OnFoo) or ON_BN_CLICKED(0, id, OnFoo)
可看出消息映射结构结构在内存中为6个DWORD,其中两个相连DWORD为 COMMAND ID 0x8204。
运行脱壳后文件,用WinHex查看进程对应内存,搜索整形数值0x8204,找到如下图位置,
这样找到了消息入口 0x00439A60.
IDA打开,找到0x00439A60出
seg000:00439A60 push ebp ; Start 消息处理
seg000:00439A61 mov ebp, esp
seg000:00439A63 push 0FFFFFFFFh
seg000:00439A65 push offset loc_4CAB59
seg000:00439A6A mov eax, large fs:0
seg000:00439A70 push eax
seg000:00439A71 mov large fs:0, esp
seg000:00439A78 sub esp, 38h
seg000:00439A7B mov eax, off_5CF3A0
seg000:00439A80 push ebx
seg000:00439A81 push esi
seg000:00439A82 push edi ; uID
seg000:00439A83 mov esi, ecx
seg000:00439A85 mov [ebp+var_24], eax
seg000:00439A88 xor ebx, ebx
seg000:00439A8A mov [ebp+var_1C], eax
seg000:00439A8D mov [ebp+var_4], ebx
seg000:00439A90 mov [ebp+var_14], eax
seg000:00439A93 mov [ebp+lpText], eax
seg000:00439A96 mov ecx, [esi+1Ch]
seg000:00439A99 xor eax, eax
seg000:00439A9B mov al, byte_620EF1
seg000:00439AA0 push ebx ; lParam
seg000:00439AA1 push ebx ; wParam
seg000:00439AA2 push 110Ah ; Msg
seg000:00439AA7 push ecx ; hWnd
seg000:00439AA8 mov byte ptr [ebp+var_4], 3
seg000:00439AAC mov [ebp+var_D], bl
seg000:00439AAF mov [ebp+var_2C], eax
seg000:00439AB2 call SendMessageA
seg000:00439AB8 push eax
seg000:00439AB9 mov ecx, esi
seg000:00439ABB mov [ebp+var_30], eax
seg000:00439ABE call CTreeCtrl::GetItemData(_TREEITEM *)
seg000:00439ABE
seg000:00439AC3 mov cl, byte_620EF1
seg000:00439AC9 test cl, cl ;cl必须为0
seg000:00439ACB jz loc_439D8F
seg000:00439ACB
seg000:00439AD1 mov ecx, eax
seg000:00439AD3 call sub_434050
seg000:00439AD3
seg000:00439AD8 test eax, eax
seg000:00439ADA jz loc_439D8F
经过反复调试,发现00439AC9处时,若跳到loc_439D8F必死,因此cl必须为0,
byte_620EF1估计是狗决定的某全局变量,查找所有byte_620EF1相关语句,设断点方便调试爆破。
将00439ACB处nop掉,继续运行到
seg028:00439C8D
seg028:00439C93 mov eax, [ebp+var_2C]
seg028:00439C96 test eax, eax ; EAX=0
seg028:00439C98 jnz loc_439D8F
seg028:00439C98
seg028:00439C9E call sub_448E20 ; ???????????
seg028:00439C9E
seg028:00439CA3 test ax, ax ; EAX=0
seg028:00439CA6 jnz loc_439D8F
seg028:00439CA6
此处又有loc_439D8F,看样子又有判断。到00439C96时EAX=1,不处理一跳即死。nop掉00439C98 和 00439CA6两处
继续运行
004354AD mov eax, [eax+1Ch]
seg028:004354B0 push 0 ; lpTimerFunc
seg028:004354B2 push edi ; uElapse
seg028:004354B3 push 68h ; nIDEvent
seg028:004354B5 push eax ; hWnd
seg028:004354B6 call SetTimer
seg028:004354BC mov al, byte_620EF1
seg028:004354C1 test al, al
seg028:004354C3 jnz short loc_435518
seg028:004354C3
seg028:004354C5 mov eax, [esi+78h]
seg028:004354C8 test eax, eax ; EAX !=0
seg028:004354C8 ;
seg028:004354CA jnz short loc_435518
此处又发现 byte_620EF1,若跳到loc_435518必死。 依前处理nop掉,运行。哈哈,一切OK.
然后通过LordPE的位置计算器,找到上述几处在文件中的位置,用UE修改保存。运行正常。
美中不足是程序启动时弹出该死的demo消息框。现在轮到处理它了。
IDA查找messagebox,居然没有查到。估计是使用间接调用了。再查找LoadLibrary与GeProcAddr,
seg000:0048BE77 mov esi, GetProcAddress
seg000:0048BE7D push offset s_Messageboxa_0 ; "MessageBoxA"
seg000:0048BE82 push edi ; hModule
seg000:0048BE83 call esi ; GetProcAddress
seg000:0048BE85 test eax, eax
seg000:0048BE87 mov dword_641DD4, eax
seg000:0048BE8C jz short loc_48BEDE
看样子真是这样干的,然后再查找dword_641DD4
seg000:0048BEC7 push [esp+0Ch+arg_4]
seg000:0048BECB push [esp+10h+arg_0]
seg000:0048BECF push dword ptr [esp+18h]
seg000:0048BED3 push ebx
seg000:0048BED4 call dword_641DD4
下断,果然在这里,以下的工作就简单了。
至此,打狗完成。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)