能力值:
(RANK:420 )
26 楼
==== 第十六章 壓縮與解壓縮 ====
│16-1 前言│
各位大爺們 ,您是否已發現到目前市面上的軟體都開始使用壓縮軟體來壓
過他們的軟體 ,使得磁片佔用量減小 ,同時也能防止被破解 ,在這麼多的優
點下 ,實在令人不得不佩服發明這種小聰明的人 ,不過由於此種做法會使得
軟體無法做適度修改 ,造成合法使用者以及盜拷者都無法修改軟體 ,這種做
法雖然對於軟體商能夠延長軟體"售命" ,不過筆者仍不贊成使用此法保護 ,
因為會解的高手仍有 ,所以這種做法簡直可說只對合法者產生某種程度的障
礙 ,因此本章就是介紹如何將軟體解壓縮。
解壓過程只適用 SYMDEB.COM (Assembly Debug) ,對於 DOS 附的DEBUG
比較不適用 ,因為缺少一些讀寫的特殊功能。
------------------------------------------------------------------
│16-2 EXE 檔的檔頭結構 │
一般的 EXE 檔有個檔頭 ,約佔用 512 Bytes 或更多 ,它的各位元代表
的意義如下: (請用pctools看EXE檔的檔頭)
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
01 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7
02 8 8 9 9 A A B B C C X X X X X X
03 X X X....
0.檔頭一開始都是 4D 5A
1.總檔案大小除以512後所得餘數
2.總檔案大小除以512後所得商數加 1
3.檔案重定位數目
4.此數*10 = 檔頭大小 ,例如 20h=512bytes
5.程式所須最小記憶體量(一般為0000)
6.程式所須最大記憶體量(一般為FFFF)
7.程式載入後的 SS-DS-10h
8.程式載入後的 SP 值
9.字組查驗和 (一般無作用)
A.程式載入後的 IP
B.程式載入後的 CS-DS-10h
C.第一個重定位表距離檔頭的位置
X.重定位表 (每4Bytes一組)
----------------------------------------------------------------------------
│16-3 解壓縮 vs DEBUG │
由於市面上軟體眾多 ,且大多附有解壓程式 ,所以我們就略過不談 ,只談PKLITE
商業版 ,相信大家都玩過 PKLITE ,它是一種能將程式壓縮後仍能夠執行的軟體 ,
其作用類似早期的 LZEXE ,只是它的商業版在存檔時 ,少了幾個重要位元 ,使得軟
體無法解壓縮 ,因此變成根本無法直接去改它 ,像一些國外來的軟體也用它壓縮 ,
其作用也只是不想被人改成隨意註冊版 ,可惜的是這樣我們根本不能將該軟體中文
化 ,所以我們必須找到方法去解壓他。
且由於壓縮軟體太多總類 ,我們也沒那麼多空間去擺解壓軟體 ,所以用DEBUG去練
習解壓才是根本的方法 ,不然硬碟遲早會不夠用的。
以下範例皆使用 SYMDEB ,如您使用 DOS 所附的 DEBUG ,請提早更新 ,以免做到
假死。
---------------------------------------------------------------------------
│16-4 PKLITE 商業版在記憶體的解壓過程 │
一般人都可能猜出該程式的解壓動做 ,即軟體載入後 ,PKLITE將該程式搬到高一點
的記憶體 ,然後解壓縮時放到原PKLITE載入時的記憶體位置 ,最後執行 EXE 檔頭重
定位以及其相關工作的工作 ,然後執行該軟體的主程式。
EXE 檔內常可見到 CALL 1234:5678 ,其中 1234會跟CS有所變動 ,這就是檔頭重定
位表的做用 ,例如原始程式是放 CALL XXXX:5678 ,但檔頭會把 XXXX 改為 XXXX+CS
然後又放回原來的地方 ,變成 CALL XXXX+CS:5678。
所以我們要在 PKLITE 執行該解檔頭動作時中斷該程式 ,並將尚未被改的原始程式
寫回磁片 ,存為 DATA.$$$ , 並利用原 PKLITE 的解檔頭的公式 ,將檔頭重定位表算
出 ,並寫回磁片 ,存為 HEAD.$$$ ,並將檔頭所有該填的資訊填回即可解壓完成。
被PKLITE壓過的軟體載入記憶體 ---> PKLITE程式將其所有程式碼搬到另一塊
空白記憶體 ---> 解壓縮 ,並將解出的資料放到原來 PKLITE 剛載入記憶體的
位置 ---> 解壓檔頭移位表以及將原始程式移位 ---> 進入原始程式(RUN)
我們就是利用程式將檔頭移位表解壓後 ,中斷其程式 ,並寫回原始程式碼 ,以及利用
原來PKLITE的移位表運算公式 ,將移位表求出來 ,寫回新檔頭資訊。
│16-5 PKLITE 商業版解壓法 │
PKLITE商業版應該有很多不同的版本 ,因為筆者已遇到兩種版本了 ,不過仍然能用
此法解壓縮 ,只是您必需確認何處才是主程式進入點 ,這點就由各位去猜測了。
範例:
筆者以手上的 XRSDOOR.EXE (V2.05) 為例 ,該軟體一開始就被 PKLITE 商業版壓
過 .尚未被其它軟體壓過 ,不過如您手上的軟體被數種軟體壓過 ,只要最後一道是
PKLITE 商業版 ,都可用此法。
G128 ---> T --> G 1D4 暫停一下(然後請確認CS:20D是RETF)
它的程式應該是
L2 MOV ES,DX
LODSW
INC AX
JZ L1
DEC AX
JZ L2
XCHG AX,CX
L3 LODSW
XCHG AX,DI
ADD ES:[DI],BX
LOOP L3
.
.
L1 .
.
.
RETF 而我們在 "L2" 處暫停 ,每個版本指令碼相同 ,但 ADDRESS 不同
記住 BX 值 ,本例值為 19DA
算出 (CS-BX)*10h = 資料長度 ,本例為2618*10h=26180h ,將末4位放到CX ,其它放
到BX ,本例 BX=2 ,CX=6180 ,然後取名為 DATA.$$$
鍵入 "W 19DA:0" ,其中19DA是剛才記住的BX值
再重新載入並執行到程式進入點 (20D-RETF後的位置)
抄下 DS.SS.CS.IP.SP
DS=19CA
SS=3E0B
CS=19DA
IP=0
SP=80
SS-DS-10=2431h
CS-DS-10=0000h
再重新載入並執行到 "L2" 處暫停 ,找一塊空白記憶體 ,填寫本程式 ,本例筆者找
9000:0 的記憶體。
LL1 MOV ES,DX
LODSW
INC AX
JZ LL2
DEC AX
JZ LL1
XCHG AX,CX
LL3 LODSW
XCHG AX,DI
PUSH AX
MOV AX,ES
SUB AX,BX
MOV CS:[BP+2],AX
MOV CS:[BP],DI
ADD BP,4
POP AX
LOOP LL3
ADD DX,0FFF
JMP LL1
LL2 INT 3
修改 CS:IP 指向剛 KEYIN 的程式
然後修改 BP 值 ,將 CS:BP 指向另一塊空白記憶體 ,本例 BP=5000h
再執行這段程式。
執行完後 ,BP會增加 ,將增加部份算出 ,填入 CX 內 ,並將其它 AX,BX,DX歸零
然後取名 HEAD.$$$ "W CS:原BP=5000" ,退回 DOS
(筆者忘記範例的BP增加多少 ,假設為2434h好了 ,將它除4=90D記下來)
鍵入
DEBUG
-N HEAD.$$$
-L 120
看看 CX 值 ,再加 20 ,然後隨意湊個大於CX+20的整數 ??00 ,例如原長 90D ,
湊整數等於 A00 ,修改 CX=長度(本例CX=A00) ,然後鍵入 "W CS:100" ,回DOS
COPY/B HEAD.$$$+DATA.$$$ UNPACK.EXE
用PCTOOLS EDIT "UNPACK.EXE" 將前兩行填入以下資料 ,只填畫線處
4D 5A XX XX XX XX 0D 09 A0 00 00 00 FF FF 31 24
^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
80 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
^^^^^ ^^^^^ ^^^^^
其餘不必動它 ,那裡該填什麼 ,可參考檔頭資料。
現在您已解壓成功啦 ,試著執行看看結果。
-------------------------------------------------------------------------
│16-6 LZEXE 解壓縮 │
筆者認為許多人手上可能沒有PKLITE商業版 ,所以再舉 LZEXE 解壓法
1.先執行 G2A -->T--> G109 暫停 (然後請確認 CS:155是JMP ,否則表示版本不同)
2.記住 BX 值
3.算出(CS-BX)*10h
4.將第3項的末四位放到CX ,第五位數以前的數字放到BX(不足者補零)
5.寫回位址為第2項的 BX:0 ,檔名 DATA.$$$ (鍵入"N DATA.$$$" 和 "W ????:0")
6.重新載入原程式
7.進入程式進入點 G2A-->T-->G155-->T
8.抄下 DS.SS.CS.IP.SP.
9.重新載入原程式
10.執行 G2A -->T-->G109
11.找一塊空白記憶體撰寫本程式 ,例如9000:0000
9000:0000 LODSB
9000:0001 OR AL,AL
9000:0003 JZ 002A
9000:0005 MOV AH,00
9000:0007 ADD DI,AX
9000:0009 MOV AX,DI
9000:000B AND DI,0FFF
9000:000F MOV CL,04
9000:0011 SHR AX,CL
9000:0013 ADD DX,AX
9000:0015 MOV ES,DX
9000:0017 PUSH AX
9000:0018 MOV AX,ES
9000:001A SUB AX,BX
9000:001C MOV CS:[BP+2],AX
9000:0020 MOV CS:[BP+0],DI
9000:0024 ADD BP,+04
9000:0027 POP AX
9000:0028 JMP 0000
9000:002A LODSW
9000:002B OR AX,AX
9000:002D JNZ 0037
9000:002F ADD DX,0FFF
9000:0033 MOV ES,DX
9000:0035 JMP 0000
9000:0037 CMP AX,0001
9000:003A JNZ 0007
9000:003C INT 3
12.修改BP值 ,使得 9000:BP 指向另一塊空白記憶體 ,如BP=5000h
13.修改CS.IP使其指向本程式
14.鍵入"G"執行它
15.算出BP增加的長度 (現在的BP-5000h)
16.將第15項之結果放到CX暫存器內
17.將AX.BX.DX清除為零
18.存檔 CS:5000h ,檔名HEAD.$$$ (鍵入 "N HEAD.$$$" 和 "W CS:5000")
19.退回DOS ,鍵入 "DEBUG HEAD.$$$"
20.鍵入 "L 120"
21.鍵入 "? CX/4" 和記下此值
22.將 (CX+20h) ,然後湊整數 ,使之符合大於(CX+20) ,且末兩位數為零
例如CX+20後 123變成200 567=600 4532=4600 6437=6500
23.將湊出之整數放到 CX
24.鍵入 "W CS:100"
25.退回DOS鍵入 "COPY/B HEAD.$$$+DATA.$$$ UNPACK.EXE"
26.DIR看看檔案長度 ,除以512byte ,的到的商和餘數轉成16進制
27.用PCTOOLS填寫 UNPACK.EXE 的前20h bytes
內容如下:
4D 5A XX XX XX XX XX XX XX XX 00 00 FF FF XX XX
^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ <-註1至註5
XX XX 00 00 XX XX XX XX 20 00 00 00 00 00 00 00
^^^^^ ^^^^^ ^^^^^ <-註6至註8
以下數字皆為低位元/高位元...別稿錯唷!
註1──填入26項的餘數
註2──填入26項的商數加1
註3──填入21項記下的數字
註4──填入22項湊整數後除以10h ,如A00=A0
註5──填入 8項的SS-DS-10
註6──填入 8項的SP
註7──填入 8項的IP
註8──填入 8項的CS-DS-10
好啦 ,解壓成功了 ,試著執行看看。
-------------------------------------------------------------------------
結論:
您是不是學到很多 ,您一定遇過用很多種軟體壓過的軟體吧 ,如先用PKLITE壓過
再用LZEXE壓過 ,再.....
您只須管它最後是什麼程式壓縮的 ,您就只須破它最後一道鎖即可 ,不用一道道解
開和反壓縮。
筆者文筆不是很好 ,且稍嫌雜亂 ,若您會組合語言 ,會TRACE壓縮軟體 ,多看幾次
相信不是很難看懂的 ,不然您就實地操作看看。
能力值:
(RANK:420 )
28 楼
==== 第十七章 Real & Protection Mode For Mameory ====
│17-1 前言│
現在的軟體保護技巧不停的翻新 ,使的筆者也要不停的練功 ,直至最進手癢
興起解保護模式的軟體時 ,發現手上的 SYMDEB 並不管用 ,甚至連 TURBO DEBUG
也無效 ,所以便四處搜刮程式 ,並研讀密笈 ,現在讓咱們來揭開這個神密的面紗
吧。
│17-1 真實模式 & 保護模式│
很多學組合語言的人可能聽過保護模式 ,但並不知道保護模式長的是什麼樣子
只知道是有著32Bit暫存器的模式 ,其實這只是一小部份罷了。
[真實模式]
當您進入 DEBUG 後 ,您便會發現記憶體是以位移方式計算程式所在位置 ,就像
1234:5678 ,且暫存器只有16Bit , 其中又使用INT中斷方式呼叫DOS所提供的工
作 ,但是由於暫存器小 ,所以您最多所能控制的記憶體量不過 1088K(FFFF:FFFF)
,當然對於真實模式大多數人都已非常了解 ,所以筆者就不多談了。
[保護模式]
DOS當初撰寫時是以8086語言來寫 ,所能使用到的記憶僅僅1088K ,所以當您主機
升級時 ,電腦超過1MB的記憶體便無法使用到 ,後來就有EMS的出現 ,但是因為EMS
設計的關係 ,只能拿來擺資料 ,無法拿來擺執行程式 ,所以比較龐大的程式便切進
保護模式 ,藉以讓程式能夠有更大的空間 ,以筆者手上的軟體而言 ,切入保護模式
的軟體有 PADS2000. Novell. 兩套軟體 ,但是WINDOW.AUTOCADR10.PADS405這些著
名的軟體並沒有真的切進保護模式 ,只是利用XMS規格切頁 ,功能類似EMS, 拿來擺
資料 ,並非拿來擺可執行的程式 ,且似乎只要掛上 HIMEM.SYS ,軟體便不能切入保
護模式。
由於筆者無法切入286保護模式 ,所以簡略帶過 ,286只有16Bit暫存器 ,保護模
式長得怎樣沒看過 ,不過286CPU有個缺陷 ,就是切入保護模式後 ,除非重開機 ,
否則回不了DOS ,當然此尚未查證。
筆者成功的切入386保護模式 ,但由於尚無法完全控制 ,所以研究的僅一知半解
,只是想將此一消息告訴各位讀者罷了.....以下所指的保護模式皆指386。
386保護模式下暫存器改為32Bit ,並從原來的 AX,BX....改成EAX,EBX....
且簡化一些暫存器 ,僅剩下 EAX.EBX.ECX.EDX.ESI.EDI.EBP.ESP.EIP.FLAGS
以及 (PF ZF IF)旗標 ,和除錯暫存器(筆者找不到此暫存器) ,而且記憶體分節
也比較怪異 ,沒有冒號囉 ,記憶體位置從00000000-FFFFFFFF ,計32MB吧 ,而且
指令也增減了一些 ,雖然程式仍可寫 int_xx ,但是皆不可呼叫 ,因為該中斷程
式所執行的不再是真實模式 ,強要執行會當機。
我想大家一定想更進一步知道什麼是保護模式 ,列一段程式給您看看吧 !
# R
EAX=7FFFFFFF EBX=00000000 ECX=00000000 EDX=00000000
ESI=00000000 EDI=00000000 EDI=00000000 ESP=00000000
EIP=00000416 FLAGS=00007246 (PF ZF IF)
# U 00000416
00000416 E7 0F OUT 0F,EAX
00000418 0F 85 88 FE 66 83 JNZ 836702A6
0000041E FA CLI
0000041F 020F ADD CL,[EDI]
00000421 85 80 FE 33 02 B8 TEST [EAX+B80233FE],EAX
00000427 FA CLI
00000428 00 CD ADD CH,CL
0000042A 14 B4 ADC AL,B4
# U 0000205C
0000205C 8B 1D 2F 07 00 00 MOV EBX,[0000072F]
00002062 E8 BF 15 00 00 CALL 00003626
00002067 0F B7 05 39 07 00 00 MOVZX EAX,word ptr [00000739]
^^^^^指令沒打錯唷
現在再來看看指令與真實模式的不同點吧 ,以下指出的是筆者測試出的部份 ,
因為市面沒有書籍介紹保護模式 ,加上筆者初學保護模式 ,所以沒有任何參考
資料 ,故稍嫌簡陋。
至於如何切入保護模式 ,由於筆者尚未學會 ,所以無可奉告。
│17-2 指令探討 │
真實模式下的程式執行結果筆者略過不談 ,因為真實模式相信學過組合語言的人
都十分了解 ,所以懶得再講一次 ,以下是保護模式執行的結果:
# A 00020000 MOV EAX,12345678
MOV AL,FF
INT 3
# T2 ("#"是類似真實模式DEBUG的"-"號 ,T2是單步執行兩次)
結果 EAX = 12345678 =123456FF
表示保護模式下也接受 AH,AL修改 ,不過好像沒有程式可改前四碼的指令 ,因為
386Debugger不接受 MOV EAH,?? 的指令 ,且我觀看其它斷落也沒看到相關的指令
所以就當做沒有這個指令吧。
再來就是指令的變化囉 ,一般學過組合的人都知道 JNZ 條件跳越僅可跳一小段距
離 ,但是保護模式似乎並無此限制 ,因為我看到一些特殊的碼 ,也列出來讓大家
看看吧。
# U 000020B5
000020B5 0F 85 7F 00 00 00 JNZ 0000213A
# U 00002111
00002111 75 27 JNZ 0000213A
從這裡可看到程式碼很明顯有著不同長度 ,不過條件跳越指令碼雙方似乎不同 ,一
個是用 "0F" 另一個用 "75" 難怪保護模式保護的軟體沒幾個人看的懂。
對了 INT_3 似乎不是觸動 0000000C-0000000F 所指的位置 ,因為我把它指向另一
塊記憶體 ,然後執行 INT_3 ,竟沒當機耶 ,而且也中斷下來了。
不要問我為什麼 ,因為我也是一知半解。
│17-3 記憶段落換算 │
接著咱們再來比較真實模式與保護模式下的記憶體位置吧:
真實模式與保護模式記憶體的換算方式書上有介紹 ,但與筆者的所研讀有點偏差 ,所
我們來看看吧 ,例如記憶體位置 1234:5678 ,轉換真實模式記憶位置可看成
12340
+ 5678
-------------
179B8 = 1000:79B8 <-----這是真實的
但是保護模式下與真實模換算就有點出入
因為 0000:0000 在保護模式下所看到的位置是 FFF00000
而 1234:5678 在保護模式下的位置是 FFF179B8
所以於保護模式下要讀寫 VIDEO 記憶體應該是 FFFB0000 or FFFB8000
不過有個地方蠻奇怪的 ,記憶位置為 FFFF:10 的記憶體保護模式下的記憶體
資料竟是從00000000開始放起 ,令人難以相信硬體如何設計 ,看來真實模式與
保護模式要有另一套的計算公式囉。
│17-4 保護模式下的中斷向量 │
真實模式下有幾個中斷是很重要的 ,稍一修改就會當機 ,如INT_8或者是
INT_1C 這些中斷每秒會被呼叫 18.2 次 , 以及INT_9(鍵盤中斷) ,這些
中斷若被改 ,應該會當機 ,但是切入保護模式後 ,這些中斷似乎就沒用到
了 ,因為我故意將這些中斷指向 0000 ,也就是將 FFF00000-FFF00100 全
部塗零 ,竟然沒有當機 ,難怪 TURBO DEBUG 不怕鍵盤被鎖死。
奇怪 ,那INT_3是指向那一塊記憶體程式呢 ?
另外程式本身也有用到 CLI 指令 ,表示仍然有程式在電腦某個腳落執行著
時間計數的功能 ,只是我找不到。
我想各位一定想再多看一些保護模式下的指令吧 ,我多列出一些碼 ,讓各位
多了解保護模式 ,與保護模式下的指令吧。
# U 2044
00002044 8B 44 24 24 MOV EAX,[ESP+24]
00002048 89 10 MOV [EAX],EDX
0000204A 8B 1D 2F 07 00 00 MOV EBX,[0000072F]
00002050 E8 D1 15 00 00 CALL 00003626
00002055 33 C0 XOR EAX,EAX
00002057 5F POP EDI
00002058 5E POP ESI
00002059 5B POP EBX
0000205A 5D POP EBP
0000205B C3 RET
0000205C 8B 1D 2F 07 00 00 MOV EBX,[0000072F]
00002062 E8 BF 15 00 00 CALL 00003626
00002067 0F B7 05 39 07 00 00MOVZX EAX,word ptr [00000739]
0000206E 5F POP EDI
接著咱們來看看其它指令 ,因為有軟體是進入保護模式後 ,才去讀寫KeyPro
指令 指令碼
OUT DX,EAX EF
CMP EDI,ESP 39 E7
OUT 6E,AL E6 6E
IN AL,DX EC
TEST [ECX],EDI 85 39
IN AL,02 E4 02
OUT 60,AL E6 60
IN AL,64 E4 64
TEST AL,02 A8 02
IN EAX,85 E5 85
IN EAX,DX ED
OUT DX,EAX EF
POPFD 9D <---指令沒打錯唷
NOP 90
既然真實模式與保護模式指令差不多 ,要DEBUG保護模式下的軟體應該不是很難
才對 ,好啦 ,筆者講到此為止 ,您是不是對保護模式已稍有概念了。
如果您對保護模式追蹤有概念的話 ,希望您也能教教筆者 ,因為保護模式的軟體
已逐漸增多 ,而我僅只有概念 ,太慘了.....