|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友0 P2 u: j/ r$ a
会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助
/ [! V$ ?1 `7 A; f$ f作者 : Detten Detten@tiscali.be 1 \- v" h" q1 z+ x. m
来源 : _blank>http://biw.rult.at/0 {: j% i) F5 a# }+ y
2 C& k* l2 \, N! c6 Z翻译 : nbw _blank>http://www.vxer.com/
9 Y9 g8 }1 M2 D+ F3 U% n. a$ J
9 V: W4 j& r- e1 o: k# ~: O1、前言) c0 `6 W9 Y p- n. I0 v, _ \0 D
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
; j* O" `3 [9 `/ c9 d 那如何来写呢?
* N6 G8 y% G1 t===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
: i) `0 S; d2 g& @/ v5 M& m# y% r1 u
===〉如果找到,打开该文件。
/ }; ~4 [* C/ V# h: ~1 |7 K' A' `$ O9 i6 v" t; O
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。
; ?, B9 w' i3 J/ ?8 q& o; j# n+ T0 u9 \7 Y1 @0 b3 e, x! ^
===〉如果以上都无误,我们可以做需要调整 : ^) J7 a& D# H
把文件指针移动到指定位置,然后写入新的操作码。
" z0 v1 f5 ~ a/ G5 g/ Z5 m% _ X* \) O
===〉关闭文件,给出提示结果。% r; n2 H% |, f
& c6 U5 X' A( }: q" h
下面找一个你破解的文件,然后开始....: a& r- F6 v) b* ]# s$ r7 ^
8 K7 R; G1 P0 F9 R- i2、必要的API
& ?3 w4 ]* }$ [0 L/ \, M7 i 做这个程序需要用到什么API呢?
, l7 c. s) R+ K J4 K
0 R/ W/ f, W) X' h/ r( IHANDLE CreateFile(
: V9 u- e. l6 T6 f' E6 |5 A2 i$ z. B
LPCTSTR lpFileName, // pointer to name of the file
' U1 \: L4 ]6 X# {7 _8 t( \DWORD dwDesiredAccess, // access (read-write) mode & t3 o- Q/ j, ]9 `# F& _# X. f8 t
DWORD dwShareMode, // share mode
4 O" u% u" M# m2 j+ D; ], KLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes # h! p: N$ e/ y; f! x6 ^' S' b
DWORD dwCreationDistribution, // how to create * k$ X) _. g$ |
DWORD dwFlagsAndAttributes, // file attributes # t% \5 T9 D1 z ?4 |0 D
HANDLE hTemplateFile // handle to file with attributes to copy 7 ^8 q5 W( H# S: i6 S
);
# v: r8 p: M: u! d+ `5 V: ?
4 ?& K* t5 S6 f 这个API函数用来打开或者创建文件。
1 s# {% s- l/ K$ s! o6 M: U; LdwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;
# L* `" Q' `9 q0 l& j4 l- EdwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'
( m2 e) L8 [% zdwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。4 d6 F4 q/ o! ^6 @2 ^ x
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。
, D: C- n& y, {% |$ I: q 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。: |' V4 b, g* a* t$ C. O
' g0 x* N+ U5 U% y+ V* \. L
BOOL WriteFile( # q1 ]+ |# ~- S
HANDLE hFile, // handle to file to write to & k' Q6 I& o7 V' e/ N
LPCVOID lpBuffer, // pointer to data to write to file % n R, H' y& {8 l
DWORD nNumberOfBytesToWrite, // number of bytes to write
* `+ n0 j7 ^! R% yLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written - [- G; L+ J0 V, ?/ i7 ^9 ~+ x, a
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O; ~& b6 W7 P% |& q& ~" g
);
' K6 q' S8 f v; m+ H9 d( x
5 d7 c, z& Z% b1 [% ? 我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]' }# D. G7 j8 i( T
涉及到的hFile句柄就是CreateFile函数的返回值。
# [: l4 j+ _/ |$ Z) _; f6 k& j* ]% @; [
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
. j1 q2 i( v/ s6 o
T. @- e, w1 o& ctypedef struct _OVERLAPPED { // o
- @/ L, z" @1 P' A5 u. m ]- QDWORD Internal; 2 c( m7 J& ^7 f# `( p- h' k( \
DWORD InternalHigh; ) a: f( G/ s& @' r
DWORD Offset;
% U3 y) a/ c" [: j) LDWORD OffsetHigh;
0 X G+ C* B% c5 _5 b+ x1 @HANDLE hEvent; 2 S ^" C1 o( w9 f8 F7 O, p; `" O
} OVERLAPPED; * K7 Z; C& D3 n6 W! b( L0 Q
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址), W8 {7 u; E4 ~
& X- @: ~5 _ L3、目标/ E3 C) F( F; e" Y6 S j3 l% [! B
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) G, z2 @. `# v8 b" Y! p" u
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:
) U0 M& {0 Q/ e2 k, S3 _
& c6 X& d( k6 j" z, w9 s: W0 T9 A( sOffset 53Fh : 74h, 15h -> 90h, 90h
% ?2 ]3 ]- S& ~, s O5 {) h6 Y
% q) I" F) P5 i! v0 |% T# D X* P: o 以上就是我们所需要的所有信息。7 ^+ Q9 Y- h$ }6 ]2 j7 e7 g& ]: m
6 }) w( m% C( {) g- K# {+ M
4、代码" i' w3 ~) f* Y+ a1 G( R2 R h
6 y: ~" q( c; }$ b/ m4 ?
3866 M& q3 x& J; T# Q# } I
.model flat,stdcall
& u. g# h: ]2 n2 \option casemap:none
3 n/ G8 P) ?" w& dinclude \masm32\include\windows.inc5 W4 @$ {9 _2 _# ?( o2 X( }
include \masm32\include\user32.inc4 z+ u+ o1 r, w+ R+ T2 M- `
include \masm32\include\kernel32.inc) O+ {/ ], y1 Y' G6 @
includelib \masm32\lib\user32.lib, C6 U. S5 R% {3 g5 ?- E
includelib \masm32\lib\kernel32.lib0 `& r6 ?; O9 l
0 \+ {" J* q+ t# L/ P0 L
5 @* Y: G% y8 X3 c7 ?: z7 y, n4 q
.data ( O/ D9 l# [! W; f9 W, m' s
FileName db "Crackme5.exe",0
. e; I5 x6 {0 C7 K4 k1 r% RAppName db "Crackme 5 Patch",0% m) q7 v( Y* w3 U# q
Done db "File patched succesfully !",0
* I) f: }' L7 N0 N* a+ v* {$ ^/ LNoFile db "Can't find crackme5.exe !",0* e# \1 h Y2 t* b# t7 \6 z
ReFile db "Wrong version of crackme5.exe !",0
. B+ j; e6 h# ?, ^WrFile db "Error writing to crackme5.exe !",0
; z; ~0 h k, \( ^RBuffer db 75h, 15h+ y5 {/ X- e s! U, ^
WBuffer db 90h,90h
/ T7 ~2 l& {. `8 TOffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
+ F: J8 f' F, V* p( B
. ]$ f3 v+ e6 j1 d2 e.data?
; \& _- r3 d4 y, W* K- q8 Q
; ^) ]0 `- ^& y: \( BhInstance HINSTANCE ?. B" V- W: O0 c6 k
CommandLine LPSTR ?
' F: B1 ~* q* q' R) f l$ o! Nhwndname HWND ?( i7 z# p; v8 l) u% D i' B
hFile HANDLE ?
- l- P& L9 w( | @6 d8 `Numb dd ?
+ M' v( D3 b) ?/ C$ O* X b- B( ]Buffer db 2 dup(?)
6 _' E! t4 r, z5 `
6 X2 `- c) @" e2 Q0 F) [& @4 V( [+ U# w8 W2 }- z4 b7 I! R
.const' \1 t% | J: `! \
1 A; i5 T" k( D' Y8 E# r" `.code
9 u8 T2 ~' v2 {) ~4 u& ]/ j1 Nstart:
% a- k; V) X: k; q; A) \% {/ Q; s: E
invoke GetModuleHandleA, NULL! b1 C- e) r2 P2 X# Y
mov hInstance,eax
9 y. y% g/ V6 j* t& s% C7 b2 @" O1 f
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL % g4 U* Z+ X5 z, t# B4 L+ [
2 K/ N3 @6 p ^ i7 O; ?.IF eax!=INVALID_HANDLE_VALUE4 x- p4 T d. K. N
' k' d! ~( t, f4 L2 l2 R
mov hFile, eax ; 存储文件句柄' n6 Q- N9 E( O
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节! _4 J+ ]9 S; I# S& R2 o" j/ h- `
mov ax, word ptr [Buffer] 2 U6 X8 [3 Z" {4 F$ p# N) P
.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-): o; O S% ?$ O& S. {3 E& Q! i$ `
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)7 H# ^, Y- [ G3 U, D' @
.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
) a' h9 P8 T( C9 X. V, jpush MB_OK % ], t5 a5 U9 ^
push OFFSET AppName' K& J/ U- G/ n( c+ y( ^
push OFFSET Done ; 弹出信息地址入栈# P& D, W4 A! \4 {9 F6 |; s
.ELSE ;如果返回值不是2,那么弹出错误信息
/ a% ?6 B/ x" T1 ?1 y5 ~- Z2 \push MB_OK OR MB_ICONINFORMATION
" f* q7 d: k. J( rpush OFFSET AppName; B: i" k# S, n: o
push OFFSET WrFile ?( z7 x* i9 T" d+ i
.ENDIF
5 ?. b: |( q S4 W v( y.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息
6 |% g6 s/ ?% C/ A; m. {push MB_OK OR MB_ICONINFORMATION
* L% j! o2 y0 b/ Epush OFFSET AppName/ K6 p: V5 D2 J& D# K+ @* m
push OFFSET ReFile
* x& ]: B) |: _6 L.ENDIF 8 u5 D( d7 m7 X1 Z/ r
' Z7 g7 m: c6 f/ k8 b. f+ c" O.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
8 r6 M# Z1 H' vpush MB_OK OR MB_ICONINFORMATION
! n" \6 v/ M7 L$ n# p# ^push OFFSET AppName
4 |8 | a7 j6 ]* F r+ ?push OFFSET NoFile 8 Z* H# U- I/ U# \" L9 a
.ENDIF Q1 ?6 i; @# M
) Q3 u9 g6 ?# s0 a
push NULL/ |- \. H! _6 T2 V
Call MessageBox q F+ n$ ]: c! z$ |' A5 `
invoke CloseHandle, hFile ; 关闭文件( L# `4 T% }, [* G
invoke ExitProcess,eax ; 退出) x: i5 I; ^2 R
+ ]: l: X' w9 o' rend start8 M7 p& c r C' i
V1 C8 n2 ]5 l" [! G, e 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
* _' p- f% `& Q, |/ c) ^( c3 ?, J2 i/ U, V
var currentpos,timer;) Y& ^( O4 N2 a3 ~6 ], N% Z3 ^% g
8 C" p4 _! r* Z! |
function initialize()& W! N1 @% j' q0 x+ h: ?2 |
{
9 A& T9 {2 x9 Y2 G6 Dtimer=setInterval("scrollwindow()",10);, B# g% r3 V' M
}1 ?, Z6 u/ G, H- Q" L3 m/ y
function sc(){* W7 Y( N7 t) f. @; S
clearInterval(timer);
) k7 G% L9 f: Q& H- @1 n' R}, _7 {' |6 P3 M: c/ d
function scrollwindow(): P+ `7 @0 n9 p7 E
{( b! Q# V5 Z, J4 p4 ]( e9 D9 D' x
currentpos=document.body.scrollTop;
1 ^9 M" K7 W* t1 L6 f5 e1 o( dwindow.scroll(0,++currentpos);/ T- u3 \; V7 ~6 b/ y) y
if (currentpos != document.body.scrollTop)1 t, v/ ]- h1 [# F' a( R* K$ t' ?' V
sc();, r, s. H3 Z/ o- b
}
4 H- ^ p+ [" b) e Cdocument.onmousedown=sc; Y& |2 p* w, ]- V T1 [
document.ondblclick=initialize/ l1 f$ F" y7 j' R2 P
5 j( \0 k/ b, s7 P. g" u* y0 Q' M
|! j: f: H) z( h) ~6 E; r
|