http://www.shnenglu.com/Files/sleepwom/cycle.zip
Name: ffff
Serial:? 11223344556677889
在所有 GetDlgItemTextA API設置斷點
004010A6? |.? 6A 11???????? push??? 11????????????????????????????????????????? ; /Count = 11 (17.)
004010A8? |.? 68 71214000?? push??? 00402171??????????????????????????????????? ; |Buffer = cycle.00402171
; 右擊 -> 數據窗口中跟隨 -> 立即數
004010AD? |.? 68 E9030000?? push??? 3E9???????????????????????????????????????? ; |ControlID = 3E9 (1001.)
004010B2? |.? FF75 08?????? push??? dword ptr [ebp+8]?????????????????????????? ; |hWnd
004010B5? |.? E8 0F020000?? call??? <jmp.&USER32.GetDlgItemTextA>?????????????? ; \GetDlgItemTextA
; 00402171? 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38 38? 1122334455667788
; 00402181? 00 98 BA DC FE 43 79 63 6C 65 43 72 61 63 6B 6D? .樅滎CycleCrackm
004010BA? |.? 0BC0????????? or????? eax, eax?????????????????????????????????????? ; 判斷 eax 是否為 0, 如果是 jump 0040111F
004010BC? |.? 74 61???????? je????? short 0040111F
004010BE? |.? 6A 11???????? push??? 11????????????????????????????????????????? ; /Count = 11 (17.)
004010C0? |.? 68 60214000?? push??? 00402160??????????????????????????????????? ; |Buffer = cycle.00402160
; 右擊 -> 數據窗口中跟隨 -> 立即數
004010C5? |.? 68 E8030000?? push??? 3E8???????????????????????????????????????? ; |ControlID = 3E8 (1000.)
004010CA? |.? FF75 08?????? push??? dword ptr [ebp+8]?????????????????????????? ; |hWnd
004010CD? |.? E8 F7010000?? call??? <jmp.&USER32.GetDlgItemTextA>?????????????? ; \GetDlgItemTextA
; 00402160? 66 66 66 66 00 00 00 00 00 00 00 00 00 00 00 00? ffff............
; 00402170? 00 31 31 32 32 33 33 34 34 35 35 36 36 37 37 38? .112233445566778
004010D2? |.? 0BC0????????? or????? eax, eax????????????????????????????????????? ; 判斷 eax 是否為 0, 如果是 jump 0040111F
004010D4? |.? 74 49???????? je????? short 0040111F
004010D6? |.? B9 10000000?? mov???? ecx, 10?????????????????????????????? ; ecx = 0x10
004010DB? |.? 2BC8????????? sub???? ecx, eax?????????????????????????????????? ;? ecx = ecx - eax (eax 此時存放用戶名的長度)
004010DD? |.? BE 60214000?? mov???? esi, 00402160???????????????????; esi 指向用戶名
004010E2? |.? 8BFE????????? mov???? edi, esi?????????????????????????????????????;? edi 指向用戶名
004010E4? |.? 03F8????????? add???? edi, eax???????????????????????????????????? ;? edi 指向用戶名后面的位置
004010E6? |.? FC??????????? cld
; 清除方向標志,在字符串的比較,賦值,讀取等一系列和rep連用的操作中,
; di或si是可以自動增減的而不需要人來加減它的值,
; cld即告訴程序si,di向前移動,std指令為設置方向,告訴程序si,di向后移動
004010E7? |.? F3:A4???????? rep???? movs byte ptr es:[edi], byte ptr [esi]
; rep 指令
;格式:REP MOVS(或REP STOS,或REP LODS);
;執行的操作:使REP后面的串操作指令重復執行,執行的次數預先存放在CX寄存器中,每執行一次串操作指令,
;CX寄存器的內容自動減1,一直重復執行到CX=0,指令才結束。具體的操作步驟是:
;第1步 如果CX=0,則退出REP,否則執行REP后面的串操作指令;
;第2步 CX ← CX-1;?
;第3步 執行串操作指令
;第4步 重復第1步~第3步。
;rep???? movs byte ptr es:[edi], byte ptr [esi]
;的意思是,重復執行? movs byte ptr es:[edi], byte ptr [esi] 這個語句,次數是 ecx 寄存器中的次數
;1. esi 指向輸入的用戶名
;2. edi 指向輸入用戶名后面的內存
;3. ecx 是通過 0x10- 輸入用戶名的長度得來的
;也就是說,如果輸入的用戶名,不足 0x10 這個長度, 就是用‘輸入的用戶名’重復去填充,直至 0x10 這個長度
;如果輸入的用戶名已經是 0x10 這個長度,那么就不做任何操作了
004010E9? |.? 33C9????????? xor???? ecx, ecx??????????????????????????????????????????????? ; ecx 清 0
004010EB? |.? BE 71214000?? mov???? esi, 00402171?????????????????????????????? ;? ASCII "11223344556677889"??; esi 指向輸入的序列號, 為 lods 指令作準備
004010F0? |>? 41??????????? /inc???? ecx???????????????????????????????????????????????????????? ; ecx 自增 1
004010F1? |.? AC??????????? |lods??? byte ptr [esi]
; 字符串操作中,從串取指令,
;從DS:SI所指向的空間中取出一個字節/字/雙字放入寄存器中AL/AX/EAX,
;同時把SI+(-)1/2/4.(LODS相當于MOV AL,[SI]?? INC SI.)
;從串取指令就是從DS:SI所指向字符串中取出一個字符.
004010F2? |.? 0AC0????????? |or????? al, al??????????????????????????? ; 判斷字符是否為 0?? 字符串結束標志
004010F4? |.? 74 0A???????? |je????? short 00401100??????????? ;如果al,即取出來的字符等于0,就是跳轉到00401100? 這里的 0 是結束字符
004010F6? |.? 3C 7E???????? |cmp???? al, 7E??????????????????????? ; 將 al 跟 0x7e 進行比較, 7e 的十進制是 126,? 7E 對應的字符是 '~'
004010F8? |.? 7F 06???????? |jg????? short 00401100?????????? ;? j 表示 jump,? g 表示 greater , 也就是說,取出來的字符如果大于 '~' 這個字符,就是跳轉到 00401100
004010FA? |.? 3C 30???????? |cmp???? al, 30??????????????????????? ; 將 al跟 0x30 進行比較,30的十進制是 48, 0x30 對應的字符是 '-'
004010FC? |.? 72 02???????? |jb????? short 00401100?????????? ; j 表示 jump, b 表示 below, jb 判斷 cf 標志位,低于時跳轉, jl 用于帶符號的運算,jb用于 無符號的運算
004010FE? |.^ EB F0???????? \jmp???? short 004010F0?????? ; 循環,直至字符串結束
00401100? |>? 83F9 11?????? cmp???? ecx, 11?????????????????? ; 判斷字符串長度是否為? 0x11
00401103? |.? 75 1A???????? jnz???? short 0040111F?????????? ; cmp 算術減法運算結果為零,就把ZF(零標志)置1.??? jnz 判斷當 ZF(零標志位)為 0 時就跳轉
00401105? |.? E8 E7000000?? call??? 004011F1
0040110A? |.? B9 01FF0000?? mov???? ecx, 0FF01
0040110F? |.? 51??????????? push??? ecx
00401110? |.? E8 7B000000?? call??? 00401190
00401115? |.? 83F9 01?????? cmp???? ecx, 1
00401118? |.? 74 06???????? je????? short 00401120??????????????????????????????? <------------- 破解關鍵點 1,?? 使 ZF 標志位 ==1
0040111A? |>? E8 47000000?? call??? 00401166
0040111F? |>? C3??????????? retn
00401120? |>? A1 68214000?? mov???? eax, dword ptr [402168]
00401125? |.? 8B1D 6C214000 mov???? ebx, dword ptr [40216C]
0040112B? |.? 33C3????????? xor???? eax, ebx
0040112D? |.? 3305 82214000 xor???? eax, dword ptr [402182]
00401133? |.? 0D 40404040?? or????? eax, 40404040
00401138? |.? 25 77777777?? and???? eax, 77777777
0040113D? |.? 3305 79214000 xor???? eax, dword ptr [402179]
00401143? |.? 3305 7D214000 xor???? eax, dword ptr [40217D]
00401149? |.^ 75 CF???????? jnz???? short 0040111A????????????????????????????? <-------------? 破解關鍵點 2, 使 ZF 標志位 ==1
0040114B? |.? E8 2B000000?? call??? 0040117B????????????????????????????????? ; 指向成功顯示"Congratulations!"
00401150? \.? C3??????????? retn
不難得出,破解有兩個關鍵點
00401105? |.? E8 E7000000?? call??? 004011F1?????????????????????????????????<------------- 作用未知
0040110A? |.? B9 01FF0000?? mov???? ecx, 0FF01??????????????????????????? <------------- ecx = 0X0FF01
0040110F? |.? 51??????????? push??? ecx????????????????????????????????????????????????? <-------------- ecx 進棧
00401110? |.? E8 7B000000?? call??? 00401190???????????????????????????????? <--------------?***** 在此設置斷點進去分析 *****
00401115? |.? 83F9 01?????? cmp???? ecx, 1????????????????????????????????????????? <------------- 只要使 ecx == 1
00401118? |.? 74 06???????? je????? short 00401120??????????????????????????????? <------------- 破解關鍵點 1,?? 使 ZF 標志位 ==1
===============================================================================================
call??? 00401190?斷點處
00401190? /$? 5F??????????? pop???? edi???????????????????????????????????????? ;? cycle.00401115
; Call 會先將返回地址入棧,再進行跳轉,這里跳轉后的第一條指令就是POP
; 明顯就是 先取出返回地址,
; 這里這么做,是為了取 ecx 的值,因為在調用call之前, 會先把 ecx 入棧
00401191? |.? 59??????????? pop???? ecx?
00401192? |.? 57??????????? push??? edi
00401193? |.? 81F9 80000000 cmp???? ecx, 80?????? ; 這里比較ecx 是否小于或等于 0x80, 如果小于或等于 0x80 ,就直接 return
00401199? |.? 7E 55???????? jle???? short 004011F0???????????????????????
; JLE∶ 指令助記符——(有符號數比較)小于或等于轉移(等價于JNG)。當SF和OF異號或ZF=1時轉移(段內直接短轉移)。
0040119B? |.? 51??????????? push??? ecx
0040119C? |.? 8BF1????????? mov???? esi, ecx
0040119E? |.? 81E1 FF000000 and???? ecx, 0FF
004011A4? |.? 8BF8????????? mov???? edi, eax
004011A6? |.? 83F9 08?????? cmp???? ecx, 8
004011A9? |.? 7E 05???????? jle???? short 004011B0
004011AB? |.? 8BFB????????? mov???? edi, ebx
004011AD? |.? C1E9 04?????? shr???? ecx, 4????????????????? ;
; SHR 指令助記符——無符號數的邏輯右移。經常用來除以2。 當移位次數大于 1時,則移位次數應預先置于CL寄存器中,寫成“SHR …,CL”。
004011B0? |>? C1C7 08?????? /rol???? edi, 8
; ROL∶ 指令助記符——循環左移。
; 格式為:ROL 目的操作數,1
; 或ROL 目的操作數,CL (其中CL中存放的是移動次數)
004011B3? |.? D1E9????????? |shr???? ecx, 1
004011B5? |.^ 75 F9???????? \jnz???? short 004011B0
004011B7? |.? C1EE 08?????? shr???? esi, 8
004011BA? |.? 23FE????????? and???? edi, esi
004011BC? |.? 81E7 FF000000 and???? edi, 0FF
004011C2? |.? 59??????????? pop???? ecx
004011C3? |>? BE 80000000?? mov???? esi, 80
004011C8? |>? 85FE????????? /test??? esi, edi
;test屬于邏輯運算指令 功能: 執行BIT與BIT之間的邏輯運算
; 兩操作數作與運算,僅修改標志位,不回送結果.
004011CA? |.? 74 20???????? |je????? short 004011EC
004011CC? |.? 33FE????????? |xor???? edi, esi
004011CE? |.? 57??????????? |push??? edi
004011CF? |.? 81E1 00FF0000 |and???? ecx, 0FF00
004011D5? |.? 87CE????????? |xchg??? esi, ecx
004011D7? |.? 32E9????????? |xor???? ch, cl
004011D9? |.? 33F1????????? |xor???? esi, ecx
004011DB? |.? 87F1????????? |xchg??? ecx, esi
004011DD? |.? 51??????????? |push??? ecx
004011DE? |.? FF05 82214000 |inc???? dword ptr [402182]
004011E4? |.? E8 A7FFFFFF?? |call??? 00401190????????????????????? ;遞歸調用
004011E9? |.? 5F??????????? |pop???? edi
004011EA? |.^ EB D7???????? |jmp???? short 004011C3
004011EC? |>? D1EE????????? |shr???? esi, 1
004011EE? |.^ 75 D8???????? \jnz???? short 004011C8
004011F0? \>? C3??????????? retn
將上面的匯編轉換成C,大概是...
#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
// 模擬ASM的 PUSH, POP 操作
template<class T>
class Stack
{
public:
?void push(T data)
?{
??vstack.push_back(data);
?}
?void pop(T& data)
?{
??if (vstack.empty())
??{
???data = 0;
??}
??else
??{
???data = vstack.back();
???vstack.pop_back();
??}
?}
private:
?vector<T> vstack;
};
typedef unsigned long DWORD;
Stack<DWORD> thisStack;
DWORD n402182 = 0xFEDCBA98;
std::vector<DWORD> g_stack;
void XChange(DWORD& a, DWORD& b)
{
?DWORD c = 0;
?c = a;
?a = b;
?b = c;
}
int SHR(DWORD& a)
{
?int nBit = a & 0x01;
?a >>= 0x01;
?return nBit;
}
void XOR_HIGH_LOW(DWORD& a)
{
?char value[2] = {0};
?memcpy(value, &a, sizeof(short));
?value[1] |= value[0];
?memcpy(&a, value, sizeof(short));
?
}
DWORD fun(DWORD nECX)
{
??? DWORD nRtn = nECX;
??? if( nECX <= 0x80 )?????? // cmp ecx, 80
??????? return nRtn;???????? // jle short 004011F0
??? thisStack.push(nECX);??? //? push ecx
??? DWORD nESI? = nECX;????? //? mov esi, ecx
??? nECX &= 0xFF;??????????? //? and ecx, 0FF
??? DWORD nEDI = 0x549417E7; // nEAX 值?? mov edi, eax? //////////////////////? EAX 值
???
??? if( nECX <= 0x08 )??????????? // cmp ecx, 8
??goto LABEL_004011B0;????? // jle short 004011B0
??? nEDI = 0x02F23D32;???????? // nEBX 值? mov edi, ebx /////////////////////?? EBX 值
??? nECX >>= 0x04;???????????? // shr ecx, 4
?
LABEL_004011B0:
?_asm rol nEDI, 8?????????? // rol edi, 8
??? int nBit = SHR(nECX);????? // SHR ecx, 1????
??? if( !nBit )
??goto LABEL_004011B0;?? // jnz short 004011B0
???
??? nESI >>= 0x08;?
??? nEDI &= nESI;
??? nEDI &= 0xFF;
??? thisStack.pop(nECX);
LABEL_004011C3:
??? nESI = 0x80;??? // mov esi, 80
LABEL_004011C8:
??? int nResult = (nESI & nEDI);
??? if( nResult == 0x00 )?????????? // test esi, edi
??????? goto LABEL_004011EC;???? // je short 004011EC
??? nEDI ^= nESI;
??? thisStack.push(nEDI);??????? // push edi
??? nECX &= 0xFF00;????????????? // and ecx, 0FF00
??? XChange(nESI, nECX);???????? // xchg esi, ecx
?XOR_HIGH_LOW(nECX);????????? // xor ch, cl
?nESI ^= nECX;??????????????? // xor esi, ecx
?XChange(nECX, nESI);???????? // xchg ecx, esi
?
??? n402182++;?? // push ecx; inc dword ptr [402182]???????? // n402182 地址
??? nECX = fun(nECX);?? // call 00401190
??? thisStack.pop(nEDI); // pop edi
??? goto LABEL_004011C3;
LABEL_004011EC:
?
??? if( SHR(nESI) != 1)
??????? goto LABEL_004011C8;
?return nECX;
}
void main()
{
?printf("0x%x\n", fun(0x0FF01));
}