|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友
3 i# Q7 e5 w/ x会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助 0 @4 Z$ t0 H4 w" V$ e: S$ }! h) z% [
作者 : Detten Detten@tiscali.be
/ L& a0 o ]3 {来源 : _blank>http://biw.rult.at/
6 ^* x9 a4 }" _( ]- Y! p6 C+ F& [0 a8 E9 o# l
翻译 : nbw _blank>http://www.vxer.com/
' f. q! K2 o: n, k% P- g2 P) U" }/ X# b2 ]: Q ]
1、前言5 C1 J& U% t- {5 Z
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。2 }: W- w& h4 h! H( B
那如何来写呢?# s5 d- E/ z& |& h9 w, a
===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。3 D4 p, I* s0 f6 p8 P/ T% _
1 z( B2 P) \' b$ ^' P- v+ O
===〉如果找到,打开该文件。" q1 \- e: W6 v5 F. I
8 c* I" E. f0 f4 e( o4 i% Q===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。' U7 f% s0 D4 r
4 A# m& o5 w7 |" Z! F6 z
===〉如果以上都无误,我们可以做需要调整 ! ~6 x. U( @; X- e" K% N
把文件指针移动到指定位置,然后写入新的操作码。 r+ [! m, j# U
& {$ Y' o. f) C9 P===〉关闭文件,给出提示结果。
* N; a r/ j+ y2 O" s1 \; p5 l7 p! _: B# [* i4 `
下面找一个你破解的文件,然后开始....
" \! j0 x3 }3 ~* F% Y, ?8 A" n0 F) a2 _* ?% O) J7 r2 O
2、必要的API
" a l2 X% k- m; ^7 h1 |7 |8 v 做这个程序需要用到什么API呢?( S$ M P. y) B. M; |; L# E0 a
( L, k3 W$ o& y/ W0 `" ?& e# p
HANDLE CreateFile( ! U/ w M( `, [, c( g+ ]$ {7 y
, f+ S. L* K X, l E3 x- S
LPCTSTR lpFileName, // pointer to name of the file
- n+ U9 A- R, t1 F; x l V. Z( VDWORD dwDesiredAccess, // access (read-write) mode 0 D5 y3 j& b. W) m+ G" s
DWORD dwShareMode, // share mode 3 d4 n L# _& n4 @" j; j4 s
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes : h% J' D9 U5 B8 q5 n1 R& ]
DWORD dwCreationDistribution, // how to create
/ \8 X3 r* r5 A$ ?DWORD dwFlagsAndAttributes, // file attributes 6 f" C G8 B3 w" `, h% Y& ]
HANDLE hTemplateFile // handle to file with attributes to copy 7 O* t& M) V7 {# s4 [- q
);! Z e% ^ o3 ~& U6 \8 t7 ^
) h2 W3 B. R j; p& ?: B" c7 n 这个API函数用来打开或者创建文件。
3 o5 K1 ?" B- X9 kdwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;
5 M9 D9 m X6 n1 DdwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'( r# H# o) i2 i/ |
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。+ f8 h4 z* w( p; v4 }6 ~: v
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。
3 n& a% I- d2 n1 D6 r7 G6 q 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。
7 _5 F& o* I3 H v$ }: Q& |, U
BOOL WriteFile(
, M9 W2 F4 u7 D* j: G( F& G1 bHANDLE hFile, // handle to file to write to
$ @+ F! a' `- C! TLPCVOID lpBuffer, // pointer to data to write to file 9 ]# T; ]9 t) ?. @0 e
DWORD nNumberOfBytesToWrite, // number of bytes to write 9 L" } n% a! r0 ?
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written 6 j. S0 G; m4 N5 H# k: @
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O; c' C f, |4 k8 t. ~# e C. y
);
0 S+ p% P9 [, A, i7 R. e, V; B, S* h0 N
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
; ^3 ]8 V2 F, [: F; N# @ 涉及到的hFile句柄就是CreateFile函数的返回值。
8 D0 w5 ?; @8 w+ L X' E& A' h0 a) C( ?2 k' o
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
( J$ x& s# d" J( J _/ R4 F/ ^7 i! ^! O' o8 b5 I
typedef struct _OVERLAPPED { // o ! {; i5 [3 t, u- j4 ]* w
DWORD Internal; " ]; ~5 z* b) r9 c3 e. m
DWORD InternalHigh; : H3 L+ w8 B# s6 ?3 N; n2 A$ _. C
DWORD Offset; . D3 j, B+ C) }0 o7 ]
DWORD OffsetHigh; & S/ N* @& ^ P. O c5 N
HANDLE hEvent; + m# l! X* T6 M
} OVERLAPPED; 5 h' R4 {! X5 Z' h/ G) [
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)
4 K7 n" H3 z9 ^0 m4 B; p0 `0 _4 P6 |* B+ x: _; s
3、目标1 A: I* z+ N$ @" Z4 Y+ [' }1 N3 O# W
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) ; A4 U3 w. y7 V$ h1 b
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:0 |" N0 f6 Z) I( v+ p7 U8 v
; C4 H) e! J) }0 a% YOffset 53Fh : 74h, 15h -> 90h, 90h
& [0 O! n9 |. J# E7 B/ Z7 p" \, t" M# P" X
以上就是我们所需要的所有信息。
" p4 E2 n: h2 ~3 r
; I6 C4 n# L& n4 C4、代码/ I) v6 Z5 k$ e3 y
& X* d) U# U, f; }! B# n3 x; p S3862 O n$ o$ y& L, L3 V9 s. r
.model flat,stdcall+ v/ y j% c! P! ]; L" K7 p# z
option casemap:none
% S5 R- `5 }6 F/ Tinclude \masm32\include\windows.inc
% \/ l& l- S- h! U0 b* Binclude \masm32\include\user32.inc/ X. F: d. a$ P' @
include \masm32\include\kernel32.inc
; |/ t1 ` T3 k1 Mincludelib \masm32\lib\user32.lib3 u9 `3 Z( t" t! T# M8 L) T
includelib \masm32\lib\kernel32.lib
% U& T* ]: `; M- `/ K, M
6 \! Y" ^) G6 u
0 ^: D) i( n0 e" @.data
) ?! N2 D1 K# c% _5 b0 U7 L2 rFileName db "Crackme5.exe",0
( P/ ?4 S7 f4 B. C+ O- L/ }AppName db "Crackme 5 Patch",01 J" a! W2 W" g4 r" _9 a
Done db "File patched succesfully !",0
! c- p$ ~ q" I# F9 p+ |NoFile db "Can't find crackme5.exe !",0- T. Z* |3 O7 _0 J8 H1 Y. W
ReFile db "Wrong version of crackme5.exe !",08 @8 K8 e! }4 ?0 E* x+ K( d
WrFile db "Error writing to crackme5.exe !",0
- I/ W0 i/ A# O& wRBuffer db 75h, 15h! Y( o5 F% m5 @" W
WBuffer db 90h,90h
- S& Z, U/ }' _8 k+ U4 \3 n POffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
( R- S( T# m8 a+ f5 o8 C: B" x 3 W6 v9 H8 y8 k' ^! j0 W
.data?: j0 J' L& s! s- k$ o F
& E( C; A ^ n( ]! @4 Q" G+ I" T
hInstance HINSTANCE ?1 A- V: t7 V0 E: z9 k: v
CommandLine LPSTR ?
0 } D* \+ |4 g8 ]hwndname HWND ?5 S. O8 b3 k7 F3 ?
hFile HANDLE ?: h, p$ {1 N( D4 S! h, s$ U
Numb dd ? E% N; a4 Y U2 P# s
Buffer db 2 dup(?) 3 j1 H4 Y: U# Y" F7 C- t/ g$ ?
- G/ W* {3 a' @ J+ G0 C, Q
' Z6 c6 i. }4 U9 D4 Q
.const
% y4 n* P; i& p+ q, b9 X0 J6 _
* L. g% Q, L2 X! w.code
. Y* R/ e c5 x7 l" A* ]6 H& T5 mstart:
; ]& c; H4 J! s( ]7 h/ o- G+ Y2 \1 Y
invoke GetModuleHandleA, NULL
2 A' ]+ w ]( ^& t$ umov hInstance,eax
! W! x$ K$ [% X& x* r
) k# @6 W% W: h0 }invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
" X8 u. Y1 h: U0 d+ R) P8 u. q- ?0 D# A. B' g) |
.IF eax!=INVALID_HANDLE_VALUE1 V/ d M+ D9 @5 L7 C0 h" K
; _ y( M5 O& c4 Y% o: b/ ?* Zmov hFile, eax ; 存储文件句柄
3 e! W9 x# R4 w) |4 I7 }. BInvoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节" r. J G& I% b8 n7 M
mov ax, word ptr [Buffer] ; t4 z- S0 S; c8 j* M! ^
.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)5 i- `4 X) N m4 f' F8 Y
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
/ M% a0 G8 w* D7 A.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
3 i% l. c0 r+ y2 d) ?7 opush MB_OK . K0 |( [- i: P' H& B, G
push OFFSET AppName- Y3 }) ?3 { j- ?; y9 s8 k; T
push OFFSET Done ; 弹出信息地址入栈
4 b; v' v3 s8 V; Y.ELSE ;如果返回值不是2,那么弹出错误信息: R& A$ k1 }- L6 `
push MB_OK OR MB_ICONINFORMATION
+ |0 c% ~% K; F) Apush OFFSET AppName" r' l/ p% A9 ]$ v8 R- l
push OFFSET WrFile
1 T: c9 [4 o- V$ r9 ^2 j7 w.ENDIF d$ s" F7 @2 h7 [ w) \4 h) x
.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息/ i! s, \( m5 h/ H( g' n4 \7 ^
push MB_OK OR MB_ICONINFORMATION C+ W' ~( b. L3 H9 }, A
push OFFSET AppName9 b0 Q" G3 y* x% {, N
push OFFSET ReFile 6 L; ~4 z5 B: c8 K$ ?- F1 {
.ENDIF : P) ~( X. C0 g$ Z
4 s, W" m. V9 R9 u- u.ELSE ; 如果未获得文件句柄,弹出文件不存在信息, K, [' j0 g7 m. g
push MB_OK OR MB_ICONINFORMATION
i g4 L6 p1 C: [push OFFSET AppName
3 Z3 r8 q9 f7 `( |4 Ppush OFFSET NoFile
* |1 [- q( S' ^# S" s r7 A) ^.ENDIF! }) G! R& s- n
8 [' e) C9 F2 T6 z' X: dpush NULL
- D- `, i: n! K2 L6 k% l: z5 wCall MessageBox% @1 {2 } N9 a, T9 F* s& `
invoke CloseHandle, hFile ; 关闭文件; W, d. @8 {1 z+ y( t8 k
invoke ExitProcess,eax ; 退出
4 C7 w/ i8 }% D1 ?7 _- i' N. s( l& [3 `: T3 a) W
end start L# w2 {$ K% K) A4 v
% w/ v# \. J; m
如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
# ~+ y8 J# W0 z: J
2 b- w3 Y6 u0 Fvar currentpos,timer;
- ]+ w; ^. u5 T: M+ ]; b4 O9 J" B/ z0 y
function initialize(); l' j# E* o0 q! R, R, o# h5 L
{
5 m' u9 ~; @/ N6 N* D% itimer=setInterval("scrollwindow()",10);4 z7 }( N3 l/ X- C
}
2 b* C4 f, W1 v5 }( lfunction sc(){8 H7 v+ w' t5 E" H# |
clearInterval(timer);
$ ]3 h0 o9 ~+ Z1 h}
1 F3 ~. y2 N; \' I: I' V/ |1 Efunction scrollwindow()3 S' I. {& @: _, U7 |# t! D& K0 z
{
. C, I$ ~" z! [+ ycurrentpos=document.body.scrollTop;% A# v8 j4 ]6 t6 N
window.scroll(0,++currentpos);3 a8 I3 {" o5 ~: Q. l7 P
if (currentpos != document.body.scrollTop)
9 G' ~) y m' S3 U" f* X; S) Dsc();
8 v& h) ~. i, Q4 V( d9 A}* W) B0 m5 A2 b% ?
document.onmousedown=sc* P- Z5 t" S h o
document.ondblclick=initialize
; G8 ^, h$ R B2 f: J: h
4 t6 J4 O- K9 e
# P( V% K4 d/ X/ g4 w* N |