数学建模社区-数学中国

标题: 编写一个文件补丁 [打印本页]

作者: 韩冰    时间: 2004-11-21 00:19
标题: 编写一个文件补丁

编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友 # ]' t( l* ^/ E, I) p& s会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助

" a4 C" m& \# `/ `' ?1 s: U

作者 : Detten Detten@tiscali.be 1 [% K4 o) X4 I3 q% e3 X 来源 : _blank>http://biw.rult.at/* L8 p' k' N f . r7 I! f# t% K/ O: p翻译 : nbw _blank>http://www.vxer.com/ & `9 E. ]) a2 |# Z) o" p& Z8 o, R' ^0 J$ I9 K3 g 1、前言% S: v: x- l& {0 W+ ?5 b 一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。 # Z1 v$ F5 d0 H- ?+ l8 N9 y 那如何来写呢?( v, ^% f8 k5 n$ y" Y! B2 a7 f ===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。 3 t8 D0 a& L8 Q9 A- B S: z3 R& d1 Z1 C) ?8 d4 v* { ===〉如果找到,打开该文件。8 f2 t6 i4 j6 F$ C5 U Z ( `# [8 `2 i+ A9 R$ Z% L1 B' K; d# U ===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。 / o3 i1 j' E, J* q! t5 k5 K9 y7 z ===〉如果以上都无误,我们可以做需要调整7 w' g. `3 t. H 把文件指针移动到指定位置,然后写入新的操作码。 + S- D/ |" q$ k( Y; G& @ 3 A) _! d8 z' v, i6 \===〉关闭文件,给出提示结果。 2 h9 I$ n8 C. O! V# X3 I + B1 I& l% a2 K1 K下面找一个你破解的文件,然后开始.... ( c8 m/ B% g x: O* K- ]" U1 } " m6 ^3 x6 h/ u) |/ ?! }. E1 @2、必要的API % T1 u; L, ~7 ^# Z 做这个程序需要用到什么API呢? + L& H9 C8 p4 p 5 ]# v7 l1 }2 n* P" S- ZHANDLE CreateFile( . z9 C3 X6 I% w. d4 l/ W4 X$ m" F" G" i+ l# F, D8 V LPCTSTR lpFileName, // pointer to name of the file 3 T" [# R3 o; p DWORD dwDesiredAccess, // access (read-write) mode 7 E: S1 Z2 W; ?9 Z) n: S DWORD dwShareMode, // share mode 3 i- G7 L3 }% Y2 k/ j5 NLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes 8 B' F0 H% l' A1 r DWORD dwCreationDistribution, // how to create % ~' J7 q% N% z( E3 f p J DWORD dwFlagsAndAttributes, // file attributes + D8 [: W& o, e8 z/ j HANDLE hTemplateFile // handle to file with attributes to copy i7 g% t H. v1 F );5 @6 m/ p6 k# o4 X$ ^ ]) h, q U8 @" v 这个API函数用来打开或者创建文件。' A1 {) K* B2 }- D, K9 t- f; i- P dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;9 F+ ^% @/ `+ Q( \, h dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'! r) Q) y$ O5 E dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。 6 j% L" T# _: _5 ~! _2 z 可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。 4 w2 D7 H; d: X7 }2 H 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。9 Y9 ?# r, v1 X0 ^7 v, J1 V6 R 5 i- M# g1 T, C BOOL WriteFile( 4 S/ U; V8 k# ~1 s HANDLE hFile, // handle to file to write to 7 }' O( T' E4 I/ K | LPCVOID lpBuffer, // pointer to data to write to file 3 `+ Z3 i8 @- s* h$ T9 u& J DWORD nNumberOfBytesToWrite, // number of bytes to write 5 w2 S3 f) c) } hLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written , T/ k- w6 m2 J4 b; w LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O% O* H5 @" B8 l5 } );; Y* \# `+ Y& T0 P 8 |0 z" @+ A9 G0 q, ^ 我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]7 |( }8 D7 @. j+ e: l 涉及到的hFile句柄就是CreateFile函数的返回值。0 [9 O2 @7 t6 _- ~. E $ F% t& D$ d4 B$ K5 p. ^6 C; y lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。 5 n W ~+ u8 G1 f: T q: T0 t( G! Z5 _9 l& } typedef struct _OVERLAPPED { // o 8 x) `; [% W# X( E3 I$ P7 k/ m1 A6 ~ DWORD Internal; * }- J4 S' P$ P2 w DWORD InternalHigh; 2 w! j( `6 m. ~, W5 P DWORD Offset; ! |, x3 X) ~& g- P5 ^% i DWORD OffsetHigh; : R/ J. P; Z$ K1 O HANDLE hEvent; 4 Y# V* ^; `, Y9 k2 C! E6 Y } OVERLAPPED; : k# j0 ?* `$ E/ Z6 ^7 F Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址) 4 O3 ^5 ~3 [# X& x! N) I6 }6 f5 t! S! E 3、目标 ! B; \0 J: E/ l& f4 y 目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) G) r P' |& e( V* j( I 当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方: 1 B6 M* o; C" X4 ] . A0 {& A) g& ~8 ~* F6 ?6 nOffset 53Fh : 74h, 15h -> 90h, 90h 4 Q/ m1 {; H0 {, H l3 t' R/ J- ], L, x 以上就是我们所需要的所有信息。4 e+ U) ^2 u1 @( g+ r/ A+ E, | : \8 G1 k, G) k. u; G* ?4、代码 8 T3 J- r8 }5 y- ^0 L$ ?- q+ m1 e! n4 ]6 @1 @5 B# C 386/ i6 G! |2 M; }) Z8 G .model flat,stdcall $ J1 {6 Z( `: [, g4 Eoption casemap:none , |- D; j3 ]* M. Ninclude \masm32\include\windows.inc / X+ S3 u- {9 v0 uinclude \masm32\include\user32.inc 0 N: f! U' B% m) P" u& ginclude \masm32\include\kernel32.inc % y- b3 k* J2 [- A- d' Gincludelib \masm32\lib\user32.lib " ^ D) b& W" wincludelib \masm32\lib\kernel32.lib& X7 a. b, m4 z: G ) N, ^* O' T1 R) J 9 d2 b+ t( T% _* Y' ^7 G$ l .data 5 p/ ]% J) S7 x6 X D FileName db "Crackme5.exe",0 # f+ Q% W4 p* d# V1 aAppName db "Crackme 5 Patch",0 ; k: D& A$ c+ J& \) I9 t$ jDone db "File patched succesfully !",07 q+ w" [/ F4 q) X' \& l5 c NoFile db "Can't find crackme5.exe !",0 ' Z" V ?# q- h% x/ d: I7 H: `ReFile db "Wrong version of crackme5.exe !",0/ [5 D3 C G, f WrFile db "Error writing to crackme5.exe !",0 : e* ]( u- I7 ~( N5 o% `8 Q! ^6 zRBuffer db 75h, 15h ) t7 u t, T0 Q* uWBuffer db 90h,90h ! I9 E0 W4 c8 W* `5 B0 ~9 SOffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL> * @ b! _% m% a & q; s# O& e: @5 b. W ^4 s.data?) R2 ` Q& B) z! |4 A K 6 |* r" F6 n: r: e! i) \hInstance HINSTANCE ?0 K- |; \' i* L9 N CommandLine LPSTR ? - j" e* _7 I2 n. {0 j9 s8 ehwndname HWND ?1 c9 ?3 W' G9 Z5 V hFile HANDLE ? 9 T% H6 W9 w# p3 hNumb dd ?' F$ _% A4 ~- u* [8 \9 B Buffer db 2 dup(?) # M+ W/ v" u4 y1 D' I+ s5 v* {7 I2 L - I0 v/ V" d7 d$ [( Z % f. r k) M) `7 X0 D.const/ k) w4 r8 M8 y4 R6 Q5 A . m% V; u: T- e! u. ?- q7 T( [ .code+ _4 o/ b6 W; y# y/ o( m6 `6 g start:1 w, i' z+ c% j4 Q. Z7 | ( c# w" ^: G5 S0 I7 ~- h5 ainvoke GetModuleHandleA, NULL ; t. b% a/ i( x# Wmov hInstance,eax # S; q8 ~, \0 X7 G3 p+ t8 y7 W: O# r invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL 9 a! S) p0 q, m$ C, E' R0 S ) A. J. S1 q& R: d.IF eax!=INVALID_HANDLE_VALUE3 _5 q% r# ~( q; e; W5 t ( d, y- M0 I( ?8 w; {% smov hFile, eax ; 存储文件句柄' N6 ?8 a( O9 F/ w0 J: p Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节$ n' d( x) |/ t& V; A2 Y+ S mov ax, word ptr [Buffer] 9 U' S4 o \: x" I8 E5 { .IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-) 1 A' a" c \- OInvoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h) ' z* W5 K' {/ d" u6 P.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息 u) q1 s! ?5 q push MB_OK 9 w! i y8 v+ y/ L4 d+ y) _9 Y push OFFSET AppName T o: P- B& X# e" Bpush OFFSET Done ; 弹出信息地址入栈 9 d9 z. o0 y8 T4 K.ELSE ;如果返回值不是2,那么弹出错误信息 , |. u3 X1 z( Hpush MB_OK OR MB_ICONINFORMATION4 J9 T$ i- _+ i2 q& Y push OFFSET AppName! V V& }; Z( I& L- w9 J4 ~3 [ push OFFSET WrFile * f+ A# F( G- t8 E.ENDIF ' |. Z* O& L* q" q5 Z6 k$ g6 V; W .ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息& L. a( T; z# l+ r" Z push MB_OK OR MB_ICONINFORMATION # [ P" p0 \' upush OFFSET AppName$ ]* B4 B* i8 `/ _& ^ push OFFSET ReFile $ i3 Z8 ^9 m0 p! W, V: m# @5 f .ENDIF . x* w% V' [4 m6 Q" W2 k2 s* J2 J; p; K .ELSE ; 如果未获得文件句柄,弹出文件不存在信息# u+ c' h" Z% C; Y* Q$ L9 [3 { push MB_OK OR MB_ICONINFORMATION0 v; V& q; c- V+ h% g* v* U" e3 M6 Q push OFFSET AppName ! T4 [' o' f- V7 @4 Upush OFFSET NoFile ) U4 u b! ~4 y6 c8 i.ENDIF- {, r' P' y5 u 9 ~5 q9 C- `$ _+ ~1 U push NULL / A5 Q3 x+ U0 o( pCall MessageBox: w2 G7 W* `4 |. T0 ]1 W invoke CloseHandle, hFile ; 关闭文件 9 M ?2 z3 K( @+ F9 Q8 Uinvoke ExitProcess,eax ; 退出 # x3 H1 P" z% Y + z* x4 k+ I4 p! L8 _end start " @( C/ Z" W7 m$ l( O3 s 6 a. p+ m5 l5 s: ] 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。 5 e' u, }# M! M5 a4 h! T7 _0 [ 0 p7 Z# T8 n" L- n% lvar currentpos,timer;3 m: R1 ^6 h; y5 Q ( n* _8 B% ]; }4 l1 y* cfunction initialize()* G* Z$ E! M' ~9 ~3 U% k {9 R% r: P: W8 P: V. \ timer=setInterval("scrollwindow()",10); ' H! O$ ?4 Y2 ]( T5 x9 d} ) S2 m9 M% O7 T3 X. ]function sc(){ 5 D; g6 y5 T: t' PclearInterval(timer);& K% K5 J. j2 {8 l8 m/ `$ e: B: c } & `/ a7 K5 f' _7 a5 i7 ~function scrollwindow() / s9 U2 c& P8 F9 i: ~/ M{5 L# ~ }; X5 J* D+ ] currentpos=document.body.scrollTop; 6 q* z" f/ q4 e* q( Dwindow.scroll(0,++currentpos);. F# p7 O4 z! {- N3 X if (currentpos != document.body.scrollTop) d9 g" k1 i9 I/ asc(); 5 b) s W/ e# y} 4 \& C3 a8 K& Y2 Xdocument.onmousedown=sc, ]7 \3 p5 O8 D1 f' F( z* ] document.ondblclick=initialize ; W4 ]/ I" O' e) T8 y' a/ x , I% c7 }' o9 z0 j$ L

\, w3 {( V6 B) {( Z






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5