|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友
! _: j# x" G2 K' X会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助
; \5 C4 F4 {, D作者 : Detten Detten@tiscali.be & U! T4 ? ~9 E+ U
来源 : _blank>http://biw.rult.at/1 o R, t h; e4 N( I% o
, T6 S4 n0 S U翻译 : nbw _blank>http://www.vxer.com/
+ ~; A$ q: t6 c" D
, \) J; E/ K( K+ ~3 O1、前言3 K* x) B/ a0 k2 G- g
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
; H, P2 B- f5 }% _+ S3 z) `9 y 那如何来写呢?4 L' X7 U# E3 G* D
===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
9 w0 `6 Z- q0 l; f
) [ ~( A+ y' _===〉如果找到,打开该文件。
& X: B, ~; {" S. t/ Q' @% d6 f6 g, O- s
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。/ b/ G2 [6 F& t( |4 r
9 M1 {, T0 P7 w# _' ]
===〉如果以上都无误,我们可以做需要调整 . K5 f: v! o3 W" o- _& x+ _
把文件指针移动到指定位置,然后写入新的操作码。
# A$ {; G6 @0 k% q
: g8 M/ l8 L( H8 a===〉关闭文件,给出提示结果。/ g1 K: f6 r4 x u
/ R0 t. b4 P+ [ r下面找一个你破解的文件,然后开始....0 D e4 ]# E1 m8 C
: B7 ]) G& _, s
2、必要的API
9 r. Z3 T( I. X0 o 做这个程序需要用到什么API呢?% J) L# M2 f! |0 L' z
+ k0 X# K' R- i# e8 m/ oHANDLE CreateFile( 5 d: ~/ E0 {& H/ x0 H- P5 u+ J6 U
' V2 q" _! f/ G( ~! {; x
LPCTSTR lpFileName, // pointer to name of the file
1 M. I$ X1 {! t1 L- [' p6 n: y* J& tDWORD dwDesiredAccess, // access (read-write) mode 7 o% ?8 v( J' |, s
DWORD dwShareMode, // share mode
$ ?) e3 |$ A) w8 j4 v9 x6 |* FLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
8 I, N, K5 \7 h ^DWORD dwCreationDistribution, // how to create : t4 O( `/ R2 L! n4 N
DWORD dwFlagsAndAttributes, // file attributes ' @% m3 [) Q l! ]% D0 j
HANDLE hTemplateFile // handle to file with attributes to copy
5 q2 B$ l9 `+ q* _ p);
8 v7 \- r* X/ {( ?& X& M
. @ d. H+ @/ @( W; K 这个API函数用来打开或者创建文件。2 h4 k3 j$ S0 s8 S
dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;2 i4 r1 \2 @4 M8 t9 n
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'3 Z1 E: P! M% [& z
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。2 N2 l' w7 Q8 u- T" p; E, @
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。 f9 I" Y# @6 Y* T4 G* O- i
如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。( z2 A6 I3 E2 L
7 H' v \8 h2 o, [ X8 ^6 i. YBOOL WriteFile( / u% A$ W" h* [
HANDLE hFile, // handle to file to write to
7 _" H0 E, e I$ C8 k: V& fLPCVOID lpBuffer, // pointer to data to write to file
: `9 X* H" l6 q! b% e% r% ]DWORD nNumberOfBytesToWrite, // number of bytes to write
. i6 C' b( h9 Z, }3 s% mLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
' n5 b1 Z( F, B( VLPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O- r5 o* m0 x; E
);8 M3 q! @. _3 R6 R) z
O+ V( r; _! Z' _( }6 p
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
7 e( ~8 e1 Q- G" } 涉及到的hFile句柄就是CreateFile函数的返回值。
9 k0 \# c* W% e, X$ A( n! y- ]
. y5 c& }' e5 s2 v! |/ wlpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
4 P9 z! i+ V$ \: t: ?3 l
) w. |9 X1 j$ Ttypedef struct _OVERLAPPED { // o 6 A6 l! m. e+ O$ M! K
DWORD Internal;
% F5 I' \3 c$ K) uDWORD InternalHigh;
3 ^3 i i, V" SDWORD Offset;
& O6 K$ s8 ~* P. hDWORD OffsetHigh; 8 @# p7 D0 |1 I/ ~+ `$ x ?' v
HANDLE hEvent; $ d6 @ z3 B- ^: y1 X; D% N
} OVERLAPPED;
' f( t9 t0 V4 O. YOffset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)# ?* _, I% r" |" [* \& J+ |
/ h; a/ x" F5 q7 H, h# }: o! u8 H3、目标4 h5 Q) W5 V* \5 T. q; @
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) 8 @( P4 j% S2 q/ C
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:% j6 {/ G' g/ V! V$ I5 d% d; y
$ L% B9 c( J5 S" p5 c! h! N9 F/ `
Offset 53Fh : 74h, 15h -> 90h, 90h
" E# ]% q5 b: B5 q* \1 z+ q% z! G& d/ H4 \4 q* T+ b
以上就是我们所需要的所有信息。 C, v) e& j- |5 K# U$ m
* {% N4 W# \: i6 E. t2 w4、代码6 {8 E, j$ w9 E W
/ [8 [& d- L4 U. i! F
386
/ P3 D" D( A' d" p1 q$ z.model flat,stdcall
* G: j' Y2 H5 V' @; K4 qoption casemap:none ( O- \6 L; F2 v, e
include \masm32\include\windows.inc
$ [: e+ Y+ i. ~5 d- g) w+ |. q. ?include \masm32\include\user32.inc
. Z' m6 l$ T% z0 \1 i& `3 [5 Oinclude \masm32\include\kernel32.inc* t0 g6 @# ^" S# p+ h+ p: l
includelib \masm32\lib\user32.lib
% L# j0 u4 z0 T0 `4 r5 b4 A" @includelib \masm32\lib\kernel32.lib
0 M, ]7 r0 L2 `7 X) q# H 4 T8 b& }" j! b
/ N; c, O# W3 k) C, ?
.data 1 {! ?/ p& T' H
FileName db "Crackme5.exe",0
/ f3 z4 G4 `$ ?0 i3 [7 F6 p. L, YAppName db "Crackme 5 Patch",0
0 A$ C1 E( j' V. Y# XDone db "File patched succesfully !",05 [# W9 x* J/ u0 P4 w& C
NoFile db "Can't find crackme5.exe !",0; P: I% i$ U8 V2 Z; S" u9 I& H
ReFile db "Wrong version of crackme5.exe !",0
; Q; k' ]1 q4 d1 q& Z3 hWrFile db "Error writing to crackme5.exe !",0
, t9 z, w1 p5 wRBuffer db 75h, 15h
- B( h- d% m1 l& jWBuffer db 90h,90h# }% E/ X* ^9 r6 W
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
# _) y0 \) Z; p2 u( P
& y3 J, Q" X* D.data?
" T- ?* \4 ^, z; A* A; `8 I
, z0 b* ?- u# i; Q V" M0 ahInstance HINSTANCE ?
$ N$ J* ]0 [: }& F9 J G9 {CommandLine LPSTR ?
& ]% f: N% G( ]7 w ?& o& P6 dhwndname HWND ?
( O% L5 V8 K* |5 E9 BhFile HANDLE ?
; n; Z8 ]2 ?, [; {0 d, F+ NNumb dd ?$ t" G" g! g6 ?( j: Z# l
Buffer db 2 dup(?)
3 x/ w: I' {) c& k% V8 v
9 ^; v9 O5 A* X3 m+ t
^+ z, o7 T' v" L: p, F, Z0 z.const
! d9 }5 @- ~9 v) [
" Z; A& w4 E* I& f' U; p* W) G& p: c& W.code) U4 a5 ~+ E" _/ |/ Z. [: z+ D
start:/ z. P ~ b+ [$ @0 }6 C
+ G: U2 `$ w1 z9 y8 v) O! M8 z" [invoke GetModuleHandleA, NULL/ S. B& ~ t- v7 b# _9 m! ~8 l' \
mov hInstance,eax
: Z% g% f U/ W/ p$ J* Q3 E9 f, Z/ F" q; a9 v
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL 3 H/ p6 \1 ~8 p {" s* R
& { r( u# T' i.IF eax!=INVALID_HANDLE_VALUE
/ a- R |) S9 q0 c4 k9 [8 \/ I& {. E e5 P
mov hFile, eax ; 存储文件句柄) N% ]. D8 W' g4 t
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节5 C8 R% g: m5 n) N# M2 {! R
mov ax, word ptr [Buffer] / q( O9 o+ I( w, [ s- ]& x& ~6 {
.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)! D& O5 S1 P; T- i' e L" b" `- k6 J" d
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)3 U: v6 J$ p% x9 A2 G
.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
! ?8 D9 m" x, @0 s, epush MB_OK 2 O0 p' R# A3 P; h O
push OFFSET AppName! x% j, N; q. L+ H; H0 q. s, F0 p- t
push OFFSET Done ; 弹出信息地址入栈
* a4 ]) Q0 Y* E! H% |! ^2 w.ELSE ;如果返回值不是2,那么弹出错误信息* g: P9 V) ]. ?' ]+ I
push MB_OK OR MB_ICONINFORMATION5 V4 l& l- t7 }. Q& g
push OFFSET AppName6 J$ f$ e, z2 `: `
push OFFSET WrFile Z8 R6 h1 v7 ~: p% ~
.ENDIF
0 K6 [* S! o( {+ N% _3 D% y.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息
* B8 B) t6 `3 ]2 j c% I7 ]. Epush MB_OK OR MB_ICONINFORMATION- C/ N1 u% O& q1 j( {* C2 Z
push OFFSET AppName4 i. G/ a- `6 ?1 m q# b- W% v
push OFFSET ReFile
- Y( o3 R% m0 t8 r4 u.ENDIF + }. z6 r' V! p2 U$ C. ^6 n6 y
: }" [0 B0 l( D' J.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
) |) c7 r# S! U Opush MB_OK OR MB_ICONINFORMATION
* G: P& h9 V, W7 K, h0 H# Gpush OFFSET AppName- m' {9 `" M0 F3 _$ s* B9 U# j+ ?
push OFFSET NoFile
) }* a0 R4 l4 R& g" e" l ^; j.ENDIF
% o T9 R' I3 G( `# K: _- W7 h o2 c
push NULL' R6 o9 o- w) F) W- T: ?
Call MessageBox
0 E. d. @9 P; ] Xinvoke CloseHandle, hFile ; 关闭文件
2 E' r5 ]5 B$ i; R# ~! yinvoke ExitProcess,eax ; 退出
8 ]- b5 h% |8 B' Y/ R; H2 B4 `/ j5 v Q& T7 B
end start6 k& w8 m# |; Y! F+ k, X
! H- G1 ?3 l1 v( }5 x
如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
4 F- j* R1 `$ O3 r: F9 x
5 N; t P3 W6 U+ A. k Wvar currentpos,timer;
& B7 \* t( k: [5 k# a# ^- e- k5 `. ^3 \" w. d- F& N, @
function initialize()
H8 X$ x4 W0 o4 W$ e h' ~; s Q{
# q9 Y4 \ ?# ztimer=setInterval("scrollwindow()",10);
( A$ r! \+ @- ~- T}
% J. g( {' U2 |function sc(){
. L% h5 ^- J2 M' Z |4 A+ Z* }& ZclearInterval(timer);' N' k" J5 Z, G2 |
}, }: n0 B7 n9 O* L- u0 h
function scrollwindow()
) m1 V; Q+ T( E2 j5 S R3 B. B- B{* I. T6 g6 T6 E0 C
currentpos=document.body.scrollTop;
) w n" S" y" C0 R- o5 [0 c9 rwindow.scroll(0,++currentpos);
: n4 L3 g8 T+ f. F1 Wif (currentpos != document.body.scrollTop)
2 J# P0 V4 G8 f0 `sc();
- c6 O J2 n: M8 r) |}8 |6 N. y6 Z7 q$ g: S% e2 e4 s" \
document.onmousedown=sc( S# N8 v( {9 m c" p/ P2 d
document.ondblclick=initialize( B4 N3 ^, w5 s9 C6 y! n
; b& |+ f4 t7 t( y! U* L* Y % E* o8 Q3 n) U$ y4 d0 G
|