|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友( i! @3 q( e$ e' W H1 q# f
会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助 7 \8 N; ?( v7 y! m0 q9 p
作者 : Detten Detten@tiscali.be x E/ f9 I/ d: D
来源 : _blank>http://biw.rult.at/
, G) G5 s }3 e; h1 t
' U: k% W" J. L+ x翻译 : nbw _blank>http://www.vxer.com/) z$ _5 t) t- M
) l `! P' {0 b' D/ g- C1、前言
" n# K- o7 g. |5 ]3 W# i- ]4 Y 一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。3 Z/ r2 q* e u! l' E/ m) [% y% |
那如何来写呢?
( h. g5 y/ _& V) @===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
9 z9 P6 S! w2 I* u* R: s5 |( [* R' |3 y/ j8 g
===〉如果找到,打开该文件。
2 Q. |1 d& A! x; I! r+ q- Y5 v: v- z5 P0 b' q0 X9 F. m
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。, P4 k1 x+ x- N5 J0 m3 j
& t1 n/ G/ M3 j4 m===〉如果以上都无误,我们可以做需要调整
$ |% W, b, C3 W& S+ a 把文件指针移动到指定位置,然后写入新的操作码。
8 N" j/ z" c! ^! F/ N% y& r6 `1 d/ }7 A; U
===〉关闭文件,给出提示结果。/ T# L. r! s* |! S; n/ F6 r
, |* L+ _* O/ R: | k8 O5 R
下面找一个你破解的文件,然后开始....
- @) w; e9 h" \5 U- a+ \+ o) e& i, t( Y5 t5 S3 M$ X
2、必要的API
E6 c$ ~9 n3 c1 ?$ W* x1 c0 \ 做这个程序需要用到什么API呢?
- U6 @' e' p/ H! @
! N& K* U0 Q& [# G6 r0 _HANDLE CreateFile(
( O# l* }$ E: P) A
- P4 o0 P0 f+ N' CLPCTSTR lpFileName, // pointer to name of the file
3 e. ]. A$ _5 u4 h2 vDWORD dwDesiredAccess, // access (read-write) mode
( `1 d1 `5 a N- [" aDWORD dwShareMode, // share mode # G2 D) |6 m! z2 Z' g
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes % a' [/ Q7 @4 I: u* j+ O% [
DWORD dwCreationDistribution, // how to create
+ j, ]$ R* ~4 b8 i' i' QDWORD dwFlagsAndAttributes, // file attributes
( g3 a3 K6 _# }! UHANDLE hTemplateFile // handle to file with attributes to copy
& T- F& w# M( [* q5 y. O/ a V);' x1 N5 c& n2 d, n" H
- e: Z3 c2 k# D+ S& L1 h# p 这个API函数用来打开或者创建文件。3 u$ v9 W, C5 u9 \) \
dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;! j6 P* Y" N- l/ Q! J
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ') y. J$ F: G! z' [) x) Y
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。
9 V5 x+ O& ^% c* x( e 可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。
$ m3 I- E |2 i# U 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。
' E; U9 H, G# ~8 u+ b2 B
$ t/ g( Z9 P* K! r0 q. o, gBOOL WriteFile( E! h# h7 R. ~+ G1 R8 x' V2 N
HANDLE hFile, // handle to file to write to
M: `1 h& f! w4 g3 VLPCVOID lpBuffer, // pointer to data to write to file
: n3 I' S2 {6 y% }' V# u( oDWORD nNumberOfBytesToWrite, // number of bytes to write
: x2 q T& [. QLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
& m& V( [) H y3 fLPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
- J0 \6 p: J X);3 @, w. S7 t; {6 S5 F. e
" d6 f+ k1 t! W3 C6 o
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]' l4 ~* c! r% G/ Y( k
涉及到的hFile句柄就是CreateFile函数的返回值。$ A( n9 `; W: H
1 m4 L: k# l3 F1 J. w3 E7 Q! O
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
. u: {% j; q0 p6 x! _6 I) Z' R/ b8 i1 _6 G% ^8 g2 G2 ~! {' l
typedef struct _OVERLAPPED { // o
9 ~% y9 r2 k* k# o7 \5 nDWORD Internal; ( B; p. y" `9 l; n; z
DWORD InternalHigh; & a y1 T6 H2 }. ^. X! q$ ^$ h
DWORD Offset; 8 u" @9 o, k6 ?/ q6 X' ?9 }
DWORD OffsetHigh; 4 z; X% Z4 J% |* q
HANDLE hEvent; ; L* m$ A. n+ [. \' p
} OVERLAPPED;
% c, E" p- B4 k! ?; i0 C0 VOffset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)- v! @, o/ S, z1 b
6 `# R% x) p) D1 j
3、目标
, u; ^, l0 v* y" i( Q3 F8 m4 P 目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行)
# i% v' H# u6 B- Q6 s2 D y+ ^ 当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:0 q6 Z* B7 \0 S( h3 g2 @/ _
* G" r% ~1 y* x$ v5 t+ U& e
Offset 53Fh : 74h, 15h -> 90h, 90h! }4 k* R {5 W) F* S0 |% A
! s' f# w7 l$ g( N7 B q+ \5 N
以上就是我们所需要的所有信息。: ?- ^0 c, H2 ~7 P! P, \1 ^
" t; h5 C6 P; @# o, r5 a% _6 N1 g
4、代码
& v0 c+ @ w/ [* z2 D9 }. Q1 E, J
# _( `' ?- I) N386
) _3 w) d! j: V6 D) f.model flat,stdcall
: V0 O6 w3 j1 x& toption casemap:none
) ?8 k* d5 S; R% K3 a0 linclude \masm32\include\windows.inc
% Z# A! I& o& s5 S0 `$ t/ C8 xinclude \masm32\include\user32.inc) v$ t* @* L n8 F* S9 }
include \masm32\include\kernel32.inc
4 ]% r% e% b( _includelib \masm32\lib\user32.lib; a& e: q/ C) t: k3 [$ \$ a2 {
includelib \masm32\lib\kernel32.lib+ x* i9 W6 P* v9 O; {& B
" o; G \# |/ K& U( F. y# j# g
$ u$ x* V! z: N
.data : u7 Z# d5 R! `/ _9 j' K( k
FileName db "Crackme5.exe",0
" g d6 L9 D7 W2 \% H4 A! ?AppName db "Crackme 5 Patch",0
$ I3 F/ J: v3 A. S j" x) RDone db "File patched succesfully !",0
' ]# a. `, N( z0 B/ N7 bNoFile db "Can't find crackme5.exe !",00 K& S7 b3 Q: x) ^' ? F3 f% h
ReFile db "Wrong version of crackme5.exe !",09 X0 {1 _$ O) Y+ F. z( h5 E
WrFile db "Error writing to crackme5.exe !",0 S" N1 s& G7 U3 X
RBuffer db 75h, 15h( U8 u* [6 F. k6 d% u
WBuffer db 90h,90h2 C& M. e) a$ Z2 N+ ]; r
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
% W! q" p, o1 o1 q
* x, _) }8 C U. h: w2 \! L/ [.data?
7 g8 `6 @3 c# f) p3 A( `
J, d% B7 d% d. a ahInstance HINSTANCE ?
- F& j) ~5 \) T# }& K( TCommandLine LPSTR ?
- l$ H/ c- D, y5 u- y8 Ghwndname HWND ?
) k3 ^; ?6 i8 M, JhFile HANDLE ?
/ a& w: d G5 y- \ k. x1 cNumb dd ?& n) z2 z: G) B9 B
Buffer db 2 dup(?) * D4 B, z5 L8 F+ @7 {; C
" v! p' o6 _1 ~( U: I4 F# c
4 R$ j0 s8 w3 n" ], {.const8 {# y+ i5 n3 e. U5 N! y g
3 b# b x7 F& |( U
.code, F/ K. O S, l' L/ i
start:' F# k0 l% e- S, I V
! `5 F9 |2 k8 {& j% L. G6 b
invoke GetModuleHandleA, NULL
8 H4 r( b# P6 ^: Y$ Smov hInstance,eax
1 P: Z ?2 v( k6 [* D6 B1 o7 }( R" } m. y) k" P9 J
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL , @- L6 ^# R8 m; p* o) m
) O% ]$ B. Y) a0 o) A2 Z0 a
.IF eax!=INVALID_HANDLE_VALUE) d* \; y" }3 C: e& ]* H6 B. R
4 h# q2 \+ d8 P) N: D4 K; v1 ~- M% X
mov hFile, eax ; 存储文件句柄
0 }! H+ \. E8 k4 @& p( JInvoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节9 @# k( o6 B7 Y6 m9 z# W4 ~( j: B
mov ax, word ptr [Buffer]
4 c2 K/ B7 g `. ?$ ^.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)
( e- D4 Z) C- B, F, K8 eInvoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
! N, d( D1 }. e8 I.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息& [ l2 X# N2 M, o$ k, w2 Q
push MB_OK 6 _* R$ z/ a* f( K, ]% r4 s
push OFFSET AppName
& j5 x% I% _# d0 T! V3 Rpush OFFSET Done ; 弹出信息地址入栈
1 ]) F E7 ?) J6 N F.ELSE ;如果返回值不是2,那么弹出错误信息( |& h6 v) x$ L4 y
push MB_OK OR MB_ICONINFORMATION3 z8 f/ Q- T* u% V0 ]" @
push OFFSET AppName: @; u7 W: [2 b& j6 ?* Q
push OFFSET WrFile
7 `: H( E) e0 `$ [1 r5 J.ENDIF
0 b$ n$ y' ]2 j: ~" ^.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息7 v4 L: g) R. s6 t3 h$ l) F! X7 [
push MB_OK OR MB_ICONINFORMATION
* p; s4 n1 j1 u+ Z8 g tpush OFFSET AppName- Q, }# Q8 s. o
push OFFSET ReFile ( [& Q$ ~/ ~! E3 b
.ENDIF
% X# N3 ~4 e, r5 g+ ?
" u3 c7 ^$ ^. A.ELSE ; 如果未获得文件句柄,弹出文件不存在信息- Q; y5 D' E% ^0 v7 P9 C: E; v% z6 k
push MB_OK OR MB_ICONINFORMATION
7 E" Y- m; f) C i I& o& @push OFFSET AppName9 {% o i" J5 p C) J) u$ X
push OFFSET NoFile
5 R+ Q# L; A: {# i4 d# Q4 t.ENDIF
. C( b) [/ A* n1 V+ |# [4 y; K' Q- O) }
push NULL
. e8 r+ m8 q' O) ^+ h( b& @Call MessageBox
1 S* h6 A, [% z/ H+ {$ O. _. L* _invoke CloseHandle, hFile ; 关闭文件- {* a' i( d! F$ v9 g4 a
invoke ExitProcess,eax ; 退出' J( a; y/ \0 m7 m# O; W, _' \
8 v/ l0 f y: e+ `
end start# u' B1 R B" q2 E7 L# H' G; \
9 |4 P* O% x: _+ N4 S- H v$ x7 w
如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
0 F4 b. t5 N2 I: }3 Z# m; X5 j- M1 W
/ @; T' J/ L' Y. Avar currentpos,timer;3 R8 f) M V Q; K5 X( ^
' t/ L( y# G% q( _
function initialize()" @& L; C a. ?3 \; `4 b
{6 ~# `8 g; P3 e
timer=setInterval("scrollwindow()",10); x3 n/ [, _. J, P
}9 G0 `" U8 F. i; }) ^
function sc(){; J( q! }* B& d& k
clearInterval(timer);. v$ i" _0 l+ N' g
}
" l, O* O, ^# `& M8 yfunction scrollwindow()
U; f% y8 q V1 @ E# J{8 E" w0 y3 l5 y4 @0 a
currentpos=document.body.scrollTop;( S5 a9 l, W f4 }# J3 j: ^. o. I
window.scroll(0,++currentpos);; E/ O& q: E6 A- u3 p' e. v% h5 m3 ~2 c
if (currentpos != document.body.scrollTop)
5 j8 t8 @+ V4 x, g: nsc();
3 n; G2 B c7 \) R+ V# E( Z; V}
4 J$ ~! T! V: qdocument.onmousedown=sc
- M9 v+ O1 K+ d2 e! L3 K/ tdocument.ondblclick=initialize
. @) j8 k6 }, v0 \' R ~9 U" C% ]3 P- B
, x7 o# m, z1 K4 M$ G/ g0 d' ^
|