|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友$ r& r; u; v# v8 C; x
会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助
2 Q$ t2 Z1 w% n作者 : Detten Detten@tiscali.be
% V' q% G% _2 B来源 : _blank>http://biw.rult.at/( ]1 E) [ k% K% t) A/ C: q# C
' r3 j8 `' s1 d$ T" [翻译 : nbw _blank>http://www.vxer.com/
0 X. ^; s4 {4 K* Q- t7 q8 u8 V5 P6 Z1 `! E+ L9 \' s
1、前言 x# a4 t; C6 R# Y
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
) [8 R/ E1 I0 w3 A 那如何来写呢?' D" _* W* W( C8 J" L5 j
===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。. L: D/ l0 g8 D$ g' q5 C9 Z
0 x" @0 X1 O0 t" T, c4 Z===〉如果找到,打开该文件。
2 Q& M* Y/ L: f1 I- m, L) S
6 I. C5 V8 {( X6 j9 Z' u===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。3 W4 m3 R" D2 M' ]/ h) I
; s: T- ^% p% Z* C
===〉如果以上都无误,我们可以做需要调整 7 V6 d6 t( N& h9 R# }% p M1 }3 J% g
把文件指针移动到指定位置,然后写入新的操作码。
0 z/ L* O0 Z9 K( i! U, U( S: O2 L+ ^# z1 h L0 M% l
===〉关闭文件,给出提示结果。* z: e0 D8 a1 C0 s
) G B$ m$ r& A q下面找一个你破解的文件,然后开始....- |% K2 M7 t4 }4 |( P& |# p
% U/ n. y+ N. a" o6 t5 b2、必要的API# y9 m" m# l- n1 M3 u. q
做这个程序需要用到什么API呢?
' @% K* W q1 Z( B5 O, B, y
" L% K1 u* ^" c, {9 U2 X* YHANDLE CreateFile(
( v o! C: ^ c; d! ^' C. |7 ]* T* m# ?, b9 `% v9 E' Q: ?& i
LPCTSTR lpFileName, // pointer to name of the file
. J8 V7 }* U( s' }( wDWORD dwDesiredAccess, // access (read-write) mode
, Y% o. Z* }2 O$ P# w$ @DWORD dwShareMode, // share mode
" T' |- ? N3 B! ]+ P iLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes ' G& k. u: c4 s8 D3 L
DWORD dwCreationDistribution, // how to create . }5 l' h; i0 v# p4 e4 r* e. v
DWORD dwFlagsAndAttributes, // file attributes
2 b& Z$ ^( C/ H; SHANDLE hTemplateFile // handle to file with attributes to copy 9 X' W% c3 t* h0 w; H$ l, m
);
' |/ C. V& g. L1 W! F4 h6 Q
" c! G% d0 Z. b/ z 这个API函数用来打开或者创建文件。
2 x" J4 V0 U: ~- o# S( |dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;
7 B5 c* ^; }! i/ D- rdwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'
5 O) \: \3 _+ GdwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。! I; \4 q6 C3 w, P6 f8 ^/ I2 y: y' O/ s
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。: z& K4 m# q! w$ c/ H1 N0 a
如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。' i0 q" n# G; c/ O5 b. e
, E4 L' K9 U( n) Y; M+ {: f$ q mBOOL WriteFile( $ ]5 N! Q' c: ]3 N0 J
HANDLE hFile, // handle to file to write to
2 N& a) A; N- \; WLPCVOID lpBuffer, // pointer to data to write to file
: t9 d) ]" D, w7 ~& _# a! @" w: nDWORD nNumberOfBytesToWrite, // number of bytes to write
: _! A$ I1 l: U4 aLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written 8 m `3 L; A' o- [
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
9 m C/ D% T; v0 R3 w$ \# j);! k4 I: {4 O7 o* S2 A; U
" k, ^: c: h3 ?; U- n 我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
0 p# c& [0 P: | 涉及到的hFile句柄就是CreateFile函数的返回值。
3 q/ Y+ g1 h& N! Z8 Z6 L& s2 [' c/ a( X
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
( M& @+ {6 E8 E
% W3 V5 q0 x6 xtypedef struct _OVERLAPPED { // o / p) ~4 d5 P6 j. y/ E
DWORD Internal; f: J7 p5 H; ?& x6 Q
DWORD InternalHigh;
' l2 P" S& }- r0 E1 s! ~DWORD Offset; ; f% m0 ?) y+ t+ k
DWORD OffsetHigh; 5 n' t7 J; A1 I" v
HANDLE hEvent; ! m; i9 t: y/ J& a) j1 w* }
} OVERLAPPED; ) s7 ^9 L( e% I2 f& R" f1 M+ D) F6 R
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)
1 t' n* y2 z ]# a9 ~; B. l+ I" m0 r! Z6 H
3、目标
9 ~+ V/ N7 T8 {7 k, x 目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行)
3 _- z2 ?+ a) m0 o1 k 当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:
# `+ d6 K' g3 O* K7 d; ]; R" t' R+ t3 X$ f9 w$ |" m/ {# v
Offset 53Fh : 74h, 15h -> 90h, 90h7 B9 h) S+ E9 \& z
/ a: f. W+ a+ L0 o n
以上就是我们所需要的所有信息。& F, {, y" i7 l+ O" \6 W# T
6 |6 ~6 A+ g# F1 T+ H) B3 o4、代码 t$ U, x1 o8 i* p' R6 b5 I8 Q
0 V5 T: P) s8 h386/ n3 E% F6 w0 |! {& M- G$ Q
.model flat,stdcall l& t2 ~! V* h. Z; w
option casemap:none
" w- |, O# Y7 n& J. Winclude \masm32\include\windows.inc$ X, c! k! P$ X7 _8 T4 B# P
include \masm32\include\user32.inc' w/ r7 B6 b u4 B
include \masm32\include\kernel32.inc
3 g& R' q/ x; G1 s$ G, ]3 {7 {includelib \masm32\lib\user32.lib6 b; u9 x* y7 J' ^! p: m9 k7 P
includelib \masm32\lib\kernel32.lib) W$ E& f$ |$ ^7 N/ B
z$ Q* c$ _& E$ g. c% y2 @
' t- m# i2 w! E& S1 N. `- }.data 0 M _2 Y/ _- {2 P0 `/ M) M8 Z' K
FileName db "Crackme5.exe",0
& }% E* Y. k+ X2 ~6 K8 Y- QAppName db "Crackme 5 Patch",0" _) e7 c, Q) v1 v4 }
Done db "File patched succesfully !",0
3 k/ o- i% b1 s$ [/ D# TNoFile db "Can't find crackme5.exe !",0$ Z$ G% X& Q: p" _3 H
ReFile db "Wrong version of crackme5.exe !",0
1 ?5 C4 K* B' f9 EWrFile db "Error writing to crackme5.exe !",01 v, V7 r; x7 \* M% h$ \
RBuffer db 75h, 15h
H, j b+ ^2 K8 [3 ZWBuffer db 90h,90h
1 X$ ]/ y7 g0 U4 L9 r wOffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL> ! }! S ]* E2 A0 `7 m
- ~8 t$ Z- i8 a
.data?" @2 ]3 z+ u' R/ Q& M9 @6 W
2 F, P' F! @1 W7 R" f% i* bhInstance HINSTANCE ?$ c+ L$ |) x, _" E
CommandLine LPSTR ?5 T3 U3 i% I/ e
hwndname HWND ?
( a$ ]: r( I1 R" o! E/ |$ p$ u" RhFile HANDLE ?
' O7 s d8 X* F- f) BNumb dd ?
* }4 Q5 E3 E; s) Q% bBuffer db 2 dup(?) ; D# `0 o3 J* q1 S5 D: ~( p4 S8 e- X$ `
N% H' K9 y& |9 j) n
0 G3 g4 a. C0 l0 [6 S
.const
& T: C3 L6 S0 J$ r0 v" x O2 J. U . k# A! ?/ n" H! e8 d- l4 `: D, [
.code
0 U7 }( `' `( U! I `6 hstart:- R$ l& ?" A0 s2 P- M
8 g( _5 h% E$ ~0 `2 Z! y6 ]invoke GetModuleHandleA, NULL' m5 z( Q# D# H& |
mov hInstance,eax 5 ~5 q" G$ N" ^, s: @
% f7 w8 I1 K5 `. n0 ]1 V3 ?invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL 3 O$ A1 b5 W I$ U
" G4 e2 [2 }) m+ o( [3 D4 t, O
.IF eax!=INVALID_HANDLE_VALUE* q3 G0 g f; f) R+ i
7 V* C- V& |. j" |3 Y3 ~mov hFile, eax ; 存储文件句柄 s/ n, N9 g! H+ b+ y
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节
8 S, h/ G" p) ~! @, Gmov ax, word ptr [Buffer]
9 h b! ^4 C9 g5 N.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)
t% \1 c. y Q. w( ?9 A* zInvoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h); v# h% z4 s8 U" |7 ^
.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
; a2 y6 j! \- o8 w, F6 k5 dpush MB_OK ( V5 l2 A4 R% `0 F
push OFFSET AppName
; e" L+ D( K2 t6 \" bpush OFFSET Done ; 弹出信息地址入栈8 `$ ` ?- ?$ \, S3 L+ c% `
.ELSE ;如果返回值不是2,那么弹出错误信息/ ~! N/ d+ `( G3 ~6 v
push MB_OK OR MB_ICONINFORMATION% P6 u$ `; u/ i) Q' \8 o# }
push OFFSET AppName2 r j# f8 B( r- [
push OFFSET WrFile( X9 O; n" J; e: [2 {
.ENDIF
4 d! R* g: m8 o% o! S, t4 c: {2 q" |; T% q.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息 H) S$ a/ l: a8 A
push MB_OK OR MB_ICONINFORMATION2 w2 z: @$ N+ p7 H
push OFFSET AppName
# ~: v+ J4 B0 @8 @; h2 _9 ppush OFFSET ReFile 4 ]* u! S1 N4 \& F5 O: h
.ENDIF
2 S) w: D1 s, z& a: w0 P4 p' B; Q( L! t" ?% g4 a, ]: V5 d
.ELSE ; 如果未获得文件句柄,弹出文件不存在信息" i2 c$ {# J4 e7 z( E
push MB_OK OR MB_ICONINFORMATION+ j5 j. \6 K7 f0 D: L5 L
push OFFSET AppName
- e. w4 o# j1 a( }: r) t' ^' Gpush OFFSET NoFile ( j7 S. F0 O$ x" l! Q
.ENDIF! z6 q' R5 k' S$ Q
+ S: f& u3 d! l) M4 P2 cpush NULL$ S# Q) A* R# ^2 q9 @$ ]! l" e
Call MessageBox* e* t- c( A+ ~3 f5 Z" i" B" c
invoke CloseHandle, hFile ; 关闭文件% f6 |3 h! V" g4 V" f
invoke ExitProcess,eax ; 退出4 Z" s! u$ L+ D5 r0 }
# X$ A+ ^* g2 P7 e3 q, E
end start
8 u1 i, `3 o& B- s, s0 J- ]
" W `6 F) Z+ B' ?( R4 F 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
( w6 b3 n3 x, l- U) T" o0 v
) _" N6 y: O! z1 Ovar currentpos,timer;0 T6 G( K( a; `. ]: b: [
( _3 D( H; s+ G
function initialize()" J* b6 L! F! N2 Y y
{+ F7 J4 w, g( o t' N
timer=setInterval("scrollwindow()",10);
" O2 f/ ~% h7 h @% O! d1 Y}
7 ]; s7 O& E; |: O& A5 R, @& ffunction sc(){8 k" [3 l' g# j# g3 S7 p
clearInterval(timer); y6 r2 t0 N2 I2 X! c' j
}4 A! e4 V t: A- B+ S
function scrollwindow()
7 J. |& V! a b! f! ^; ?& ]8 j{
+ j! `1 w! z; v; r! o: c5 U1 {5 D. Ycurrentpos=document.body.scrollTop;
- b$ d: g6 u+ t4 } Wwindow.scroll(0,++currentpos);: ^9 P/ q3 L7 c6 g& B* A1 j
if (currentpos != document.body.scrollTop)
; H& g* {) P. p( ~0 Jsc();
+ [2 d d9 O) A}
/ D6 v( d6 v8 C& s. G2 t" Ldocument.onmousedown=sc
+ t- w Y' i4 m% B+ }: c) ]" Qdocument.ondblclick=initialize
H7 R3 k2 J* f- C0 u
! O) d( w5 J6 }4 Q5 T9 K , E* `+ F; L+ Y! S" t0 @
|