IP_tools2.06加密演算法揭祕 ,雁南飛老兄務請一進,呵呵 (30千字)
IP_TOOLS2.06加密演算法揭密
幾周前看見罈子上在討論IP_TOOLS2.06,本菜鳥對IP工具較感興趣,就想拿來試試手,happy一下。
誰知試了一週,花了n個小時(n>40),暈菜無數次,都沒搞定,只好走人咯,鬱悶啊!這陣放假,
本想再試試,整理些資料就算了,沒想到竟還大致搞明白了,暈倒!(由於這個破程式n鬱悶本菜
鳥,本菜不禁多吐了些苦水,各位老兄還請多包涵啊:))好吧,言歸正傳,下面我們開始吧:)
這個檔案註冊失敗會彈出訊息框,偶就想用MessageBox,MessageboxEx以及生成訊息框,對話方塊的那
些API來攔截,沒想到都欄不到,鬱悶偶半天。後來用VC的SPY++看(softice中用hwnd應該也能看得
來),才發現IP_tools中的對話方塊訊息框大多使用他們自己開發的類如TRegisterDlg,TRegisterDlg2,
TMessageForm, 而不是windows自帶的Dialog類。乖乖,敵人的做工還很細噢,菜鳥很佩服的恨恨的說。
(如果有時間,研究一下如何自定義視窗類實現模式對話方塊訊息框的效果倒是很有意思)
用CreateWindowExa倒是可以攔下,不過好像有點怪,菜鳥沒有繼續,就改攔截HMEMCPY了。
windows 9X下,HMemcpy是在16bit保護模式執行,被攔截下時的ES暫存器是目的地址的段selector,
通過softice的GDT ****檢視該段的詳細資訊,段的初始地址就是32位下的目的地址。對這個
地址下bpm跟噢,很快程式就會被這個段點攔截下來,看一下是32位模式下的串拷貝,一般使
用ESI, EDI, 那就接著對EDI-1(或 2,4)(其實減不減都差不多啦)下bpm,繼續跟啊。折騰了半天,
發現了程式進行計算和比較的地方了,算是取得了點階段性的成果,呵呵。不過菜鳥到這花了7,8個小時,
菜啊,傷心噢。菜鳥使用使用者名稱是happy, 密碼是1112222,
注:
*本文中的數字都是16進位制數
*文中有時指標與指標指向的值混用,不過應該能看出來什麼時候是什麼
下面看程式:
CODE:004AC629 mov
eax, [ebp+var_10] // d eax, 看到使用者名稱happy,
CODE:004AC62C call
sub_49D94C //對使用者名稱進行操作,返回加密後
的字串長度
CODE:004AC631 mov
edi, eax
CODE:004AC633 lea
edx, [ebp+var_10]
CODE:004AC636 mov
eax, [esi]
CODE:004AC638 mov
eax, [eax+1F4h]
CODE:004AC63E call
sub_4236DC
CODE:004AC643 mov
eax, [ebp+var_10] //d eax, 看到11112222
CODE:004AC646 call
sub_49D9E8 //對密碼進行操作
CODE:004AC64B cmp
di, ax
CODE:004AC64E jnz
loc_4AC7CA //到了4ac7ca我們就不happy了,
CODE:004AC654 mov
eax, ds:off_4E128C //4e128c中存放的是地址4e3434,
是使用者名稱加密後的存放地址
CODE:004AC659 mov
edx, 1FFh
CODE:004AC65E call
sub_49D930 //對加密後的使用者名稱計算
CODE:004AC663 mov
edi, eax
CODE:004AC665 mov
eax, ds:off_4E1190 //4e1190中存放的是地址4e3634,
是密碼加密後的存放地址
CODE:004AC66A mov
edx, 1FFh
CODE:004AC66F call
sub_49D930 //對加密後的密碼計算
CODE:004AC674 cmp
edi, eax
CODE:004AC676 jnz
loc_4AC7CA
CODE:004AC67C mov
eax, ds:off_4E128C //這以下按雙字比較 4e3434+7,
4e3634+7空間中的內容
CODE:004AC681 add
eax, 7
CODE:004AC684 mov
eax, [eax]
CODE:004AC686 mov
edx, ds:off_4E1190
CODE:004AC68C add
edx, 7
CODE:004AC68F cmp
eax, [edx]
CODE:004AC691 jnz
loc_4AC7CA
CODE:004AC697 lea
edx, [ebp+var_8] //三次比較都成功了,註冊成功的對
話框就跳出來了噢
。。。。。
CODE:004AC6D8 mov
eax, offset aThankYouForReg ; "Thank you for registering IP-To"
//到這菜鳥才注意到這個字串,要是開始時就
查詢這個子串也許省偶很多事噢,心痛心痛!
。。。。。。
CODE:004AC7CA mov
eax, offset aSorryYourReg_0 ; "Sorry, your registration number or "
// game
over 的字串!Go to hell!
CODE:004AC7CF call
sub_444700
先看一下 int 49D930(int i, char *pChar), 該函式對 (pChar+0B)開始的字元竄按字求和, 長度為 i-0B (i=1ff)。
讓我們看一下重要的兩個call 49d94c,49d9e8.
*** 49d94c:
CODE:0049D94C push
ebp
。。。。。。
CODE:0049D9A8 push
eax
CODE:0049D9A9 push
offset unk_4E3434
CODE:0049D9AE push
ebx
CODE:0049D9AF push
offset unk_4DCB62
CODE:0049D9B4 push
offset unk_4DCC62
CODE:0049D9B9 call
sub_49DFFA //加密的核心函式
CODE:0049D9BE movsx
eax, al
。。。。。。
CODE:0049D9D8 retn
CODE:0049D9D8 sub_49D94C endp ; sp = -210h
*** 49d9e8:
CODE:0049D9E8 push
ebp
CODE:0049D9E9 mov
ebp, esp
CODE:0049D9EB add
esp, 0FFFFFDFCh
CODE:0049D9F1 push
ebx
CODE:0049D9F2 mov
[ebp+var_4], eax
CODE:0049D9F5 mov
eax, [ebp+var_4]
CODE:0049D9F8 call
sub_4040FC
CODE:0049D9FD xor
eax, eax
CODE:0049D9FF push
ebp
CODE:0049DA00 push
offset loc_49DA62
CODE:0049DA05 push
dword ptr fs:[eax]
CODE:0049DA08 mov
fs:[eax], esp
CODE:0049DA0B lea
edx, [ebp+var_204]
CODE:0049DA11 mov
ecx, 1FFh
CODE:0049DA16 mov
eax, [ebp+var_4]
CODE:0049DA19 call
sub_49D880 //將輸入密碼當作16進位制數解讀,
如‘11112222’被轉換成4個位元組:
11 11 22
22,稱之為密碼1
CODE:0049DA1E lea
eax, [ebp+var_204]
CODE:0049DA24 push
eax
CODE:0049DA25 push
offset unk_4E3634
CODE:0049DA2A mov
eax, [ebp+var_4]
CODE:0049DA2D call
sub_403F48 //計算密碼1的位元組長度
CODE:0049DA32 sar
eax, 1 //計算密碼1的字長度
CODE:0049DA34 jns
short loc_49DA39
CODE:0049DA36 adc
eax, 0
CODE:0049DA39
CODE:0049DA39 loc_49DA39:
; CODE XREF: sub_49D9E8+4Cj
CODE:0049DA39 push
eax
CODE:0049DA3A push
offset unk_4DCD66
CODE:0049DA3F push
offset unk_4DCE66
CODE:0049DA44 call
sub_49DFFA //核心加密演算法
CODE:0049DA49 movsx
ebx, al
CODE:0049DA4C xor
eax, eax
CODE:0049DA4E pop
edx
CODE:0049DA4F pop
ecx
CODE:0049DA50 pop
ecx
CODE:0049DA51 mov
fs:[eax], edx
CODE:0049DA54 push
offset loc_49DA69
CODE:0049DA59
CODE:0049DA59 loc_49DA59:
; CODE XREF: CODE:0049DA67j
CODE:0049DA59 lea
eax, [ebp+var_4]
CODE:0049DA5C call
sub_403CCC
CODE:0049DA61 retn
CODE:0049DA61 sub_49D9E8 endp ; sp = -210h
看到這,菜鳥就發暈了,使用者名稱和密碼1竟然都用相同演算法(49dffa)加密,再比較其加密後的值,這不是要
搞出逆演算法才行嗎?過分啊!
下面看 一下49dffa的引數:
sub_49dffa(char * pBuffToCode, char *pDestBuff, int iLenBuffToCode, char *pBuff,
char *pLongIntZ)
當進行使用者名稱加密時是:
sub_49dffa('happy', 4e3434, 5, 4dcb62,4dcc62)
當進行密碼1加密時是:
sub_49dffa( '11 11 22 22', 4e3634, 4, 4dcd66, 4dce66)
其中4dce66空間算裝內容與4dcc62完全相同,長度為50h個位元組。4dcd66與4dcb62空間內容不同。
下面我們進 49dffa去看:
sub_49dffa(char * pBuffToCode, char *pDestBuff, int iLenBuffToCode, char *pBuff,
char *pLongIntZ)
CODE:0049DFFA push
ebp
CODE:0049DFFB mov
ebp, esp
CODE:0049DFFD push
ebx
CODE:0049DFFE push
esi
CODE:0049DFFF mov
esi, [ebp+arg_0]
CODE:0049E002 mov
ebx, [ebp+arg_8]
CODE:0049E005 push
esi
CODE:0049E006 call
sub_49F121 //返回pLoingIntZ指向字串的bit數,
從pLongIntZ+2a*2的字的高位元往下
找第一個非零bit位,這裡返回280
CODE:0049E00B pop
ecx
CODE:0049E00C add
eax, 7
CODE:0049E00F sar
eax, 3 //計算修正後pLongIntZ位元組數,50
CODE:0049E012 movzx
edx, bx
CODE:0049E015 cmp
eax, edx //比較iLenBuffTocode與pLongIntZ長度,小等於則繼續
//從演算法角度來說,這個比較很有必要噢
CODE:0049E017 jge
short loc_49E01E
CODE:0049E019 or
eax, 0FFFFFFFFh
CODE:0049E01C jmp
short loc_49E055
CODE:0049E01E ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049E01E
CODE:0049E01E loc_49E01E:
; CODE XREF: sub_49DFFA+1Dj
CODE:0049E01E push
ebx
CODE:0049E01F push
offset unk_4E3838
CODE:0049E024 push
[ebp+arg_10]
CODE:0049E027 call
sub_49DF4D //將pBufTofCode 拷到4e3838
CODE:0049E02C add
esp, 0Ch
CODE:0049E02F push
esi
CODE:0049E030 push
[ebp+arg_4]
CODE:0049E033 push
offset unk_4E3838
CODE:0049E038 push
offset unk_4E38B8
CODE:0049E03D call
sub_49F15D //重點!
CODE:0049E042 add
esp, 10h
CODE:0049E045 push
[ebp+arg_C]
CODE:0049E048 push
offset unk_4E38B8
CODE:0049E04D call
sub_49DFBA
CODE:0049E052 add
esp, 8
CODE:0049E055
CODE:0049E055 loc_49E055:
; CODE XREF: sub_49DFFA+22j
CODE:0049E055 pop
esi
CODE:0049E056 pop
ebx
CODE:0049E057 pop
ebp
CODE:0049E058 retn
14h
CODE:0049E058 sub_49DFFA endp
下面跟進sub_49f15d(char *pDest, char *pSource, char *pBuff, char *pLongIntZ)
pDest==4e38b8, pSource==4e3838 ;
pSource, pBuff, pLongIntZ說指向的數實際是超長正整數,和一般的32bit的正整數一樣,低位在前,高位在後,
不同是的長度>4,輸入引數最大字數只有28,是pLongIntZ的長度,從而決定操作字竄長度不超過28+2=2a,長度
值存在空間4dcf6a中。sub_49e386用來copy字串,copy字的長度一般是2a。
sub_49F15D proc near
; CODE XREF: sub_49DFFA+43p
CODE:0049F15D
; CODE:0049F3DEp ...
CODE:0049F15D
CODE:0049F15D var_88 = byte ptr -88h
CODE:0049F15D var_6 = word ptr -6
CODE:0049F15D var_4 = dword ptr -4
CODE:0049F15D pDest = dword ptr 8
CODE:0049F15D pSource = dword ptr 0Ch
CODE:0049F15D pBuff = dword ptr 10h
CODE:0049F15D pLongIntZ = dword ptr 14h
CODE:0049F15D
CODE:0049F15D push
ebp
CODE:0049F15E mov
ebp, esp
CODE:0049F160 add
esp, 0FFFFFF78h
CODE:0049F166 push
ebx
CODE:0049F167 push
esi
CODE:0049F168 push
edi
CODE:0049F169 mov
ebx, [ebp+pLongIntZ]
CODE:0049F16C mov
edi, [ebp+pBuff]
CODE:0049F16F mov
esi, [ebp+pDest]
CODE:0049F172 push
1
CODE:0049F174 push
esi
CODE:0049F175 call
sub_49E3AC
CODE:0049F17A add
esp, 8
CODE:0049F17D cmp
word ptr [edi], 0 ;
CODE:0049F17D
;
CODE:0049F17D
;
CODE:0049F181 jnz
short loc_49F1B7 -->跳
。。。
CODE:0049F1B7 cmp
word ptr [ebx], 0
CODE:0049F1BB jnz
short loc_49F1D4 -->NZ, 跳
。。。
CODE:0049F1D4 movsx
edx, ds:word_4DCF68 ;
CODE:0049F1D4
;
CODE:0049F1DB cmp
word ptr [ebx+edx*2-2], 0
CODE:0049F1E1 jge
short loc_49F1ED --〉等0,跳
。。。
CODE:0049F1ED ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F1ED
CODE:0049F1ED loc_49F1ED:
; CODE XREF: sub_49F15D+84j
CODE:0049F1ED push
ebx
CODE:0049F1EE push
[ebp+pSource]
CODE:0049F1F1 call
sub_49E2B7 //比較大小,pLongIntZ必須大等於pSource!
CODE:0049F1F6 add
esp, 8
CODE:0049F1F9 test
ax, ax
CODE:0049F1FC jl
short loc_49F208
CODE:0049F1FE mov
eax, 0FFFFFFFDh
CODE:0049F203 jmp
loc_49F33C
CODE:0049F208 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F208
CODE:0049F208 loc_49F208:
; CODE XREF: sub_49F15D+9Fj
CODE:0049F208 push
ebx
CODE:0049F209 push
edi
CODE:0049F20A call
sub_49E2B7 //比較大小,pLongIntZ必須大等於pBuff(why?)
CODE:0049F20F add
esp, 8
CODE:0049F212 test
ax, ax
CODE:0049F215 jl
short loc_49F221
CODE:0049F217 mov
eax, 0FFFFFFFCh
CODE:0049F21C jmp
loc_49F33C
CODE:0049F221 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F221
CODE:0049F221 loc_49F221:
; CODE XREF: sub_49F15D+B8j
CODE:0049F221 mov
dx, ds:word_4DCF68
CODE:0049F228 mov
[ebp+var_6], dx
CODE:0049F22C push
ebx
CODE:0049F22D call
sub_49F121 //計算pLongIntZ的bit數,=280,
CODE:0049F232 pop
ecx
CODE:0049F233 add
eax, 20h //為運算增加20bits,
CODE:0049F236 sar
eax, 4 //計算需要的字數(280+20)/10
CODE:0049F239 mov
ds:word_4DCF68, ax //4DCF68=2A
CODE:0049F23F push
ebx
CODE:0049F240 call
sub_49E8B3 //重要初始化!!!!!
CODE:0049F245 pop
ecx
CODE:0049F246 test
eax, eax
CODE:0049F248 jz
short loc_49F25F --〉跳
CODE:0049F24A mov
cx, [ebp+var_6]
。。。
CODE:0049F25F ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F25F
CODE:0049F25F loc_49F25F:
; CODE XREF: sub_49F15D+EBj
CODE:0049F25F push
edi
CODE:0049F260 call
sub_49E3DB //計算pBuff所指向的空間的最高非零字的位置
CODE:0049F265 pop
ecx
CODE:0049F266 test
ax, ax
CODE:0049F269 jnz
short loc_49F272 --〉nz, 跳
CODE:0049F26B xor
eax, eax
CODE:0049F26D jmp
loc_49F33C
CODE:0049F272 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F272
CODE:0049F272 loc_49F272:
; CODE XREF: sub_49F15D+10Cj
CODE:0049F272 movsx
edx, ax
CODE:0049F275 shl
edx, 4
CODE:0049F278 mov
[ebp+var_4], edx ebp+var_4初始存放pBuff有效bit數,
CODE:0049F27B movsx
ecx, ax
CODE:0049F27E add
ecx, ecx
CODE:0049F280 add
edi, ecx
CODE:0049F282 add
edi, 0FFFFFFFEh //移pBuff高位的第一個字到edi,
CODE:0049F285 mov
bx, 8000h
CODE:0049F289 jmp
short loc_49F291
CODE:0049F28B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F28B
CODE:0049F28B loc_49F28B:
; CODE XREF: sub_49F15D+137j
CODE:0049F28B shr
bx, 1
CODE:0049F28E dec
[ebp+var_4]
CODE:0049F291
CODE:0049F291 loc_49F291:
; CODE XREF: sub_49F15D+12Cj
CODE:0049F291 test
[edi], bx
CODE:0049F294 jz
short loc_49F28B
CODE:0049F296 dec
[ebp+var_4] //找到了第一個非零bit,當前bit位數減一
CODE:0049F299 push
[ebp+pSource]
CODE:0049F29C push
esi
CODE:0049F29D call
sub_49E386 //用 pSource 初始化 pDes
CODE:0049F2A2 add
esp, 8
CODE:0049F2A5 shr
bx, 1
CODE:0049F2A8 test
bx, bx
CODE:0049F2AB jnz
short loc_49F30E --〉跳
CODE:0049F2AD mov
bx, 8000h
CODE:0049F2B1 sub
edi, 2
CODE:0049F2B4 jmp
short loc_49F30E
CODE:0049F2B6 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049F2B6
CODE:0049F2B6 loc_49F2B6:
; CODE XREF: sub_49F15D+1BAj
CODE:0049F2B6 push
esi
CODE:0049F2B7 push
esi
CODE:0049F2B8 lea
eax, [ebp+var_88]
CODE:0049F2BE push
eax
CODE:0049F2BF call
sub_49E94F //call sub_49e94f(tempBuf, pDest,pDest);!!!!!
CODE:0049F2C4 add
esp, 0Ch
CODE:0049F2C7 lea
edx, [ebp+var_88]
CODE:0049F2CD push
edx
CODE:0049F2CE push
esi
CODE:0049F2CF call
sub_49E386 //copy tempBuf到 pDest
CODE:0049F2D4 add
esp, 8
CODE:0049F2D7 test
[edi], bx //pBuff當前bit位的值是否為1?
CODE:0049F2DA jz
short loc_49F2FF
CODE:0049F2DC push
[ebp+pSource] //=1繼續
CODE:0049F2DF push
esi
CODE:0049F2E0 lea
ecx, [ebp+var_88]
CODE:0049F2E6 push
ecx
CODE:0049F2E7 call
sub_49E94F //call sub_49e94f(tempBuf, pDest, pSource);!!!!
//這裡竟然還有pSource作引數,菜鳥一度暈菜!
CODE:0049F2EC add
esp, 0Ch
CODE:0049F2EF lea
eax, [ebp+var_88]
CODE:0049F2F5 push
eax
CODE:0049F2F6 push
esi
CODE:0049F2F7 call
sub_49E386 //copy tempBuf到 pDest
CODE:0049F2FC add
esp, 8
CODE:0049F2FF
CODE:0049F2FF loc_49F2FF:
; CODE XREF: sub_49F15D+17Dj
CODE:0049F2FF shr
bx, 1 //bx移位
CODE:0049F302 test
bx, bx
CODE:0049F305 jnz
short loc_49F30E
CODE:0049F307 mov
bx, 8000h
CODE:0049F30B sub
edi, 2 //edi指向pBuff的當前字
CODE:0049F30E
CODE:0049F30E loc_49F30E:
; CODE XREF: sub_49F15D+14Ej
CODE:0049F30E
; sub_49F15D+157j ...
CODE:0049F30E mov
eax, [ebp+var_4]
CODE:0049F311 add
[ebp+var_4], 0FFFFFFFFh //當前bit位減一
CODE:0049F315 test
eax, eax //遍歷完pBuff?
CODE:0049F317 jnz
short loc_49F2B6 --〉no則跳
CODE:0049F319 push
0
CODE:0049F31B lea
edx, [ebp+var_88]
CODE:0049F321 push
edx
CODE:0049F322 call
sub_49E3AC
CODE:0049F327 add
esp, 8
CODE:0049F32A call
sub_49F0DA
CODE:0049F32F mov
cx, [ebp+var_6]
CODE:0049F333 mov
ds:word_4DCF68, cx
CODE:0049F33A xor
eax, eax
CODE:0049F33C
CODE:0049F33C loc_49F33C:
; CODE XREF: sub_49F15D+4Ej
CODE:0049F33C
; sub_49F15D+55j ...
CODE:0049F33C pop
edi
CODE:0049F33D pop
esi
CODE:0049F33E pop
ebx
CODE:0049F33F mov
esp, ebp
CODE:0049F341 pop
ebp
CODE:0049F342 retn
CODE:0049F342 sub_49F15D endp
CODE:0049F342
這裡有兩個call,sub_49E8B3 和 sub_49e94f。
先看sub_49e8b3, 首先將pLongIntZ的地址存入4DD76C+0。4dd76c+4開始的空間存放了16個地址,
那些地址指向的空間用來存放pLongIntZ*2^n (n=1到16), 把pLongIntZ*2^n(n=0到16)的
最高位元組存到4DD7B0+2*n, 把pLongIntZ*2^n(n=0到16)的次高位元組存到4DD7D2+2*n, 便於
後面比較大小時使用。
sub_49e94f, 是最核心的函式了,好長啊,從49e94f到49f0d9,好在結構還比較簡單,呵呵
來看sub_49e94f(char *pTempDest, char *pLongIntX, char *pLongIntY)
CODE:0049E94F sub_49E94F proc near
; CODE XREF: sub_49F15D+162p
CODE:0049E94F
; sub_49F15D+18Ap
CODE:0049E94F
CODE:0049E94F var_6 = word ptr -6
CODE:0049E94F var_4 = dword ptr -4
CODE:0049E94F arg_0 = dword ptr 8
CODE:0049E94F arg_4 = dword ptr 0Ch
CODE:0049E94F arg_8 = dword ptr 10h
CODE:0049E94F
CODE:0049E94F push
ebp
CODE:0049E950 mov
ebp, esp
CODE:0049E952 add
esp, 0FFFFFFF8h
CODE:0049E955 push
ebx
CODE:0049E956 push
esi
CODE:0049E957 push
edi
CODE:0049E958 mov
edi, [ebp+arg_8]
CODE:0049E95B mov
ebx, [ebp+arg_0]
CODE:0049E95E push
[ebp+arg_4]
CODE:0049E961 push
offset dword_4DDF74
CODE:0049E966 call
sub_49E872 //該函式首先將pLongIntX的地址存入4ddf74。
4ddf74+4開始的15個DW空間存放地址,這些地
址指向的空間的值為 pLongIntX*2^n,n=1到15
CODE:0049E96B add
esp, 8
CODE:0049E96E movsx
eax, ds:word_4DCF68
CODE:0049E975 add
eax, eax
CODE:0049E977 add
eax, ebx
CODE:0049E979 add
eax, 0FFFFFFFEh
CODE:0049E97C mov
[ebp+var_4], eax //ebp+var4儲存pTempDest的最高字地址
CODE:0049E97F mov
esi, [ebp+var_4]
CODE:0049E982 sub
esi, 2 //esi儲存pTempDest次高字地址
CODE:0049E985 push
0
CODE:0049E987 push
ebx
CODE:0049E988 call
sub_49E3AC //初始化ptempDest指向的空間為0
CODE:0049E98D add
esp, 8
CODE:0049E990 push
edi
CODE:0049E991 call
sub_49E3DB //計算pLongIntY的字長
CODE:0049E996 pop
ecx
CODE:0049E997 mov
[ebp+var_6], ax //pLongIntY字長存入ebp+bar_6
CODE:0049E99B cmp
[ebp+var_6], 0
CODE:0049E9A0 jnz
short loc_49E9A9 -->nz跳
CODE:0049E9A2 xor
eax, eax
CODE:0049E9A4 jmp
loc_49F0D3
CODE:0049E9A9 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049E9A9
CODE:0049E9A9 loc_49E9A9:
; CODE XREF: sub_49E94F+51j
CODE:0049E9A9 movsx
edx, [ebp+var_6]
CODE:0049E9AD add
edx, edx
CODE:0049E9AF add
edi, edx
CODE:0049E9B1 add
edi, 0FFFFFFFEh //edi儲存pLongIntY的當前字的地址
CODE:0049E9B4 jmp
loc_49F0BF --〉跳
CODE:0049E9B9 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
CODE:0049E9B9
CODE:0049E9B9 loc_49E9B9:
; CODE XREF: sub_49E94F+77Cj
CODE:0049E9B9 push
ebx
CODE:0049E9BA call
sub_49E83C //將pTempDest移高一個字,也就是
將pTempDest*2^16(這步非常重要噢!)
CODE:0049E9BF pop
ecx
CODE:0049E9C0 test
byte ptr [edi+1], 80h //比較pLongIntY當前字的第15bit,
CODE:0049E9C4 jz
short loc_49E9D7
CODE:0049E9C6 push
0
CODE:0049E9C8 push
ds:off_4DDFB0 //ds:off_4DDFB0存有pLongIntX*2^15的指標
CODE:0049E9CE push
ebx
CODE:0049E9CF call
sub_49E199 //兩超長正整數相加,存回pTempDest,
//位元組間的進位處理還晃了本菜一下,呵
CODE:0049E9D4 add
esp, 0Ch
CODE:0049E9D7
CODE:0049E9D7 loc_49E9D7:
; CODE XREF: sub_49E94F+75j
......
CODE:0049EB12
CODE:0049EB12 loc_49EB12:
; CODE XREF: sub_49E94F+1B0j
CODE:0049EB12 test
byte ptr [edi], 1
CODE:0049EB15 jz
short loc_49EB28
CODE:0049EB17 push
0
CODE:0049EB19 push
ds:dword_4DDF74
CODE:0049EB1F push
ebx
CODE:0049EB20 call
sub_49E199
CODE:0049EB25 add
esp, 0Ch
CODE:0049EB28
//以上對edi+1,和edi的各個非零位元,將pTempDest加上相應的pLongIntX*2^n
CODE:0049EB28 loc_49EB28:
; CODE XREF: sub_49E94F+1C6j
CODE:0049EB28 mov
ecx, [ebp+var_4]
CODE:0049EB2B mov
ax, [ecx] //ax=pTempDest的最高字的值
CODE:0049EB2E sub
ax, ds:word_4DD7D0 //4dd7d0儲存了 pLongIntZ*2^16
的最高字的值
CODE:0049EB35 test
ax, ax
CODE:0049EB38 jg
short loc_49EB6B //pTempDest大就跳到49eb6b
CODE:0049EB3A test
ax, ax
CODE:0049EB3D jnz
short loc_49EB7C
CODE:0049EB3F mov
dx, [esi] //dx=pTempDest的次高字的值
CODE:0049EB42 cmp
dx, ds:word_4DD7F2 //4dd7d0儲存了 pLongIntZ*2^16
的次高字的值
CODE:0049EB49 ja
short loc_49EB6B //pTempDest大就跳到49eb6b
CODE:0049EB4B mov
cx, [esi]
CODE:0049EB4E cmp
cx, ds:word_4DD7F2
CODE:0049EB55 jnz
short loc_49EB7C //小於就跳過49eb6b
CODE:0049EB57 push
ds:off_4DD7AC
CODE:0049EB5D push
ebx
CODE:0049EB5E call
sub_49E2B7 //比較pTempDest與pLongIntZ*2^16大小
CODE:0049EB63 add
esp, 8
CODE:0049EB66 test
ax, ax
CODE:0049EB69 jl
short loc_49EB7C //小於就跳走
CODE:0049EB6B
CODE:0049EB6B loc_49EB6B:
; CODE XREF: sub_49E94F+1E9j
CODE:0049EB6B
; sub_49E94F+1FAj
CODE:0049EB6B push
0
CODE:0049EB6D push
ds:off_4DD7AC
CODE:0049EB73 push
ebx
CODE:0049EB74 call
sub_49E1E6 //將pTempDest指向的值減去pLongIntZ*2^16
CODE:0049EB79 add
esp, 0Ch
。。。。。。
CODE:0049F068
CODE:0049F068 loc_49F068:
; CODE XREF: sub_49E94F+6DAj
CODE:0049F068
; sub_49E94F+6F2j ...
CODE:0049F068 mov
eax, [ebp+var_4]
CODE:0049F06B mov
ax, [eax]
CODE:0049F06E sub
ax, ds:word_4DD7B0
CODE:0049F075 test
ax, ax
CODE:0049F078 jg
short loc_49F0AB
CODE:0049F07A test
ax, ax
CODE:0049F07D jnz
short loc_49F0BC
CODE:0049F07F mov
dx, [esi]
CODE:0049F082 cmp
dx, ds:word_4DD7D2
CODE:0049F089 ja
short loc_49F0AB
CODE:0049F08B mov
cx, [esi]
CODE:0049F08E cmp
cx, ds:word_4DD7D2
CODE:0049F095 jnz
short loc_49F0BC
CODE:0049F097 push
ds:dword_4DD76C
CODE:0049F09D push
ebx
CODE:0049F09E call
sub_49E2B7
CODE:0049F0A3 add
esp, 8
CODE:0049F0A6 test
ax, ax
CODE:0049F0A9 jl
short loc_49F0BC
CODE:0049F0AB
CODE:0049F0AB loc_49F0AB:
; CODE XREF: sub_49E94F+729j
CODE:0049F0AB
; sub_49E94F+73Aj
CODE:0049F0AB push
0
CODE:0049F0AD push
ds:dword_4DD76C
CODE:0049F0B3 push
ebx
CODE:0049F0B4 call
sub_49E1E6
CODE:0049F0B9 add
esp, 0Ch
//以上依次將pTempDest與pLongIntZ*2^n(n=16到0)比較大小,大等則將pTempDest減去pLongIntZ*2^n
//看出這實值是什麼了嗎?是將pTempDester mod(pLongIntZ)啊!!!
CODE:0049F0BC
CODE:0049F0BC loc_49F0BC:
; CODE XREF: sub_49E94F+72Ej
CODE:0049F0BC
; sub_49E94F+746j ...
CODE:0049F0BC sub
edi, 2 //下移pLongIntY的當前字
CODE:0049F0BF
CODE:0049F0BF loc_49F0BF:
; CODE XREF: sub_49E94F+65j
CODE:0049F0BF mov
ax, [ebp+var_6]
CODE:0049F0C3 add
[ebp+var_6], 0FFFFh
CODE:0049F0C8 test
ax, ax //pLongIntY的字都讀完了嗎?
CODE:0049F0CB jnz
loc_49E9B9 --〉nz跳
CODE:0049F0D1 xor
eax, eax
CODE:0049F0D3
CODE:0049F0D3 loc_49F0D3:
; CODE XREF: sub_49E94F+55j
CODE:0049F0D3 pop
edi
CODE:0049F0D4 pop
esi
CODE:0049F0D5 pop
ebx
CODE:0049F0D6 pop
ecx
CODE:0049F0D7 pop
ecx
CODE:0049F0D8 pop
ebp
CODE:0049F0D9 retn
CODE:0049F0D9 sub_49E94F endp
看出來sub_49e94f(char *ptempDest, char *pLongIntX, char *pLongIntY)做了什麼嗎?說出來
簡單s了,就是 (*pTempDest)=((*pLongIntX)*(*pLongIntY))mod (*pLongIntZ)啊!具體推理
菜鳥就不寫了,手寫不動了啊:) 各位應該能推得出來,不然要加油噢。
哇,菜鳥到這快寫完了噢,開心啊:) 各位是不是看得也有點累了?呵呵
OK! 快要勝利了噢,現在結合sub_49F15D虛擬碼來看看就究竟是怎麼回事吧!
sub_49f15d(char *pDest, char *pSource, char *pBuff, char *pLongIntZ)
{
初始化pLongIntZ*2^n(n=1到16,其實可以認為n=0到16)
從高位到底位找到 pBuff的第一個非0位元位,初始化(*pDest)=(*pSource);
對此後從高到底的pBuff的每個位元位
{
sub_49e94f(tempBuf, pDest,pDest);!
(*pDest)=(*tempBuf);//這兩行實際上是(*pDest)=(*pDest)^2
mod (*pLongIntZ);
if(當前bit位值==1)
{
sub_49e94f(tempBuf, pDest,pSource);!
(*pDest)=(*tempBuf);//這兩行實際上是(*pDest)=(*pDest)*(*pSource)
mod (*pLongIntZ);
這裡的pSource前期一度讓偶認為無法求出逆演算法
}
}
}
實質上, 最終(*pDest)=(*pSource)^m mod (*pLongIntZ) , m是由pBuff決定的一個常數!偶用*pSorce=1
試了一下,(*pDest)果然等於1,哈哈。。。還試了一個*pSource=10, *pBuff=07, 這時
*Dest=00 00 00 10,perfect!哈!
對於偶的例子,就是要求
當
sub_49f15d(char *pDest1, "happy", 4dcb62, 4dcc62)
sub_49f15d(char *pDest2, '11 11 22 22', 4dcb66, 4dce66)
*4dcc62=*4dce66
時,要求
1)*pDest1的位數=*pDest2的位數,
2)*pDest1的第8位開始的DW等於*pDest2的第8位開始的DW。
3)*pDest1的第0B位開始的位元組和等於*pDest2的第0B位開始的位元組和。
嗯,一切都很明瞭了吧!可是對於 x^m mod Z =y, m,Z常數,知道y,怎麼求x? 菜鳥不會啊!應該有什
麼公式吧?不知道和RSA演算法有沒有什麼關係?不過,本菜鳥被這破程式折騰得夠嗆啊,實在是不想再動了。好
了,就到這裡吧!IP_TOOLS,go to hell!呵呵。。。這是本菜第一次寫關於破解的東東,沒有什麼經
驗,希望各位沒有看得暈菜過去噢,呵
半點星
02/02/13
相關文章
- 應用加密1;非對稱加密演算法揭祕2018-11-02加密演算法
- HTTP常用請求頭大揭祕2021-02-25HTTP
- 貼一個教程,Ace FTP 1.30 ,菜鳥請進! (13千字)2001-03-27FTP
- 揭祕區塊鏈的核心技術之“雜湊與加密演算法”2018-08-22區塊鏈加密演算法
- 揭祕區塊鏈的核心技術之「雜湊與加密演算法 」2018-08-15區塊鏈加密演算法
- 《CSS揭祕》——CSS進階必備2016-12-06CSS
- [譯]揭祕 React 服務端渲染2019-03-03React服務端
- 揭祕TPM安全晶片技術及加密應用2017-11-15晶片加密
- 《CSS揭祕》筆記(一)2018-03-26CSS筆記
- 閆燕飛:Kafka的高效能揭祕及優化2018-05-03Kafka優化
- Spring @Transactional 宣告式事務揭祕2018-08-23Spring
- 方正飛騰3.1加密狗破解過程-----淺談Sentinel Super Pro的加密演算法 (14千字)2015-11-15加密演算法
- 【譯】CSS 十六進位制顏色揭祕2019-03-04CSS
- 揭祕網路主播“東哥”利用快手端小程式月入30萬的祕密2021-11-09
- css揭祕 - 背景與邊框 [一]2019-04-18CSS
- 《css揭祕》學習筆記(一)2017-07-03CSS筆記
- 揭祕JavaScript中謎一樣的this2014-01-05JavaScript
- 揭祕ThreadLocal2019-03-04thread
- 揭祕instancetype2018-04-19
- 揭開Future的神祕面紗——任務取消2018-09-04
- 揭祕任務型對話機器人(上篇)2018-06-14機器人
- 揭祕任務型對話機器人(下篇)2018-06-14機器人
- 揭祕遊戲版號交易:一個版號30萬 假協議逃避監管2020-08-13遊戲協議
- EMEDITOR V3.0破解過程~~~~~呵呵~~~~~我第一次寫過程~~~~累死我了~~~~呵呵
(14千字)2001-01-11
- 一張圖揭祕Google眼鏡工作原理2013-04-10Go
- 一張圖揭祕谷歌眼鏡工作原理2013-04-16谷歌
- 翻譯一篇文章,希望大家喜歡。呵呵…… (4千字)2001-11-07
- 揭開Future的神祕面紗——任務執行2018-11-03
- 破解XFtpSvr =====> 請進 (5千字)2001-07-01FTPVR
- 首次直播揭祕 Dubbo Ecosystem:從微服務框架到微服務生態2019-01-04微服務框架
- 揭祕前端儲存2019-04-09前端
- synchronized底層揭祕2020-11-30synchronized
- Java 8 Lambda 揭祕2016-04-23Java
- 揭祕Oracle雲(一):建立雲資料庫2019-05-12Oracle資料庫
- 工行資料中心高階經理 李雁南:介面冒煙測試方法2016-11-15
- 降低30%視訊位元速率,窄帶高清技術實現揭祕2018-11-20
- 華章揭祕系列精品圖書(《Android應用開發揭祕》、《GWT揭祕》、《Spring技術內幕》)2010-01-25AndroidSpring
- 細粒度物體檢測演算法的升級揭祕2019-10-12演算法