|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友
9 G. P; `7 m9 f! T会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助
( `. ]9 T2 D6 I2 E作者 : Detten Detten@tiscali.be 9 P6 O) i9 @1 X2 N0 c% i/ d6 I
来源 : _blank>http://biw.rult.at/' O, H1 ]5 K1 d' @" t
, K& J3 I1 s0 e0 c9 W/ Q/ x! j翻译 : nbw _blank>http://www.vxer.com/ V% T; {) H% q0 W7 ]2 K
6 y! [/ L. y( x4 a6 \- r
1、前言8 d4 H+ {# V; e0 J9 \, I/ a& L+ |
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。5 i) c( @+ o; N, f$ ]' t
那如何来写呢? c" L- z( h7 A8 U$ G
===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
& D; R# x; W) v8 @/ W% D1 w# \' w) a$ p6 I% q6 S7 R
===〉如果找到,打开该文件。
! o& r# Z* P+ c% i+ x7 s# y4 K3 ?2 [: g# D
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。. B) G$ |! N5 t0 @3 ]
2 _' z4 L1 t, ^) o4 Y===〉如果以上都无误,我们可以做需要调整
9 A# n: D$ f( C) r! x 把文件指针移动到指定位置,然后写入新的操作码。
: P$ ` Q% Z2 _+ `4 t) E. _% L/ {1 P* y5 Q2 ]1 ^; {3 {
===〉关闭文件,给出提示结果。6 C: z6 n: J& c+ Q
- W' t) K5 J N$ `: N6 }下面找一个你破解的文件,然后开始....& u g8 ~( f8 u/ k2 z# u- V
& n$ @" c1 c# ]2、必要的API
- b2 Q8 C* b0 M- A 做这个程序需要用到什么API呢?
( Y& t* w8 G! r% K, ~/ `- i( N! a9 H/ f1 y* j
HANDLE CreateFile( / x6 x& ^" Q' F' _4 D; D" x Y0 Y% @
Y3 H* ]2 h3 X1 Q# H1 ILPCTSTR lpFileName, // pointer to name of the file & `" O0 e9 a9 N$ K" {* o
DWORD dwDesiredAccess, // access (read-write) mode , b5 }1 S& e2 I; X) h$ ~' o
DWORD dwShareMode, // share mode 9 P5 d& F4 U. I0 O
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
9 n8 h I) a4 G1 |7 M0 x; aDWORD dwCreationDistribution, // how to create g1 f+ K+ X* m. e/ I' w6 o
DWORD dwFlagsAndAttributes, // file attributes
. S) J. f: a( H% B3 c# mHANDLE hTemplateFile // handle to file with attributes to copy 6 a( J5 ?5 p+ ~: {3 p
);, [+ o. G8 [7 v4 h9 d
* q, l% [( I$ \ 这个API函数用来打开或者创建文件。" D. i) I; b1 i! t2 a F
dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;
/ x8 i5 T) ?& l3 PdwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'% X7 ]$ H) p% S- L+ {4 x6 G: }
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。
; t, m G$ \& h9 x2 u. m) ^6 n 可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。. x$ S7 {' g+ u$ q D* a
如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。7 }! W2 k; m. S
" _6 J' e5 j( Y# o/ l
BOOL WriteFile(
: ~* B7 N) v: d+ YHANDLE hFile, // handle to file to write to
. f7 _. m* x. w# t2 ~# w5 h3 OLPCVOID lpBuffer, // pointer to data to write to file
" k. X( Z2 h! U# A' q8 E, E- e/ _DWORD nNumberOfBytesToWrite, // number of bytes to write 5 y" {; @: i; c
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written 9 F* O# ?- C# A* f5 I
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
0 I+ L; M3 T$ q s7 x8 p" ]);
# K. T: O8 Y/ }; i: w! p/ ?: l0 `
, W* u) n5 ~9 G1 N 我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
, w: S$ E9 q7 F) |% j$ e 涉及到的hFile句柄就是CreateFile函数的返回值。) u$ C" ^! i7 e1 e+ e9 W
9 s w, M' B! s" G2 p1 l
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
2 D2 n) z3 a8 ?& K- \
6 J$ b' O8 P3 [, rtypedef struct _OVERLAPPED { // o
. C6 X5 E/ K cDWORD Internal; " W4 G& p V) \
DWORD InternalHigh; ) J" @2 N% @% H; M3 H: L
DWORD Offset;
; o3 V! T4 }5 _: A& j; z0 dDWORD OffsetHigh;
, {/ g/ e0 N& j zHANDLE hEvent; - ]* d- V2 u" K2 }
} OVERLAPPED; 9 S9 ~$ o, t/ O; J" b9 m) X
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)
- {0 S( Y. I1 O3 w. u
|& j: [9 D$ S" }! P: J3、目标( z% y( A* i q4 r2 e4 ~
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) 0 }/ N" [ G2 r& s; t
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:
/ |( f, X4 z) x2 _, }- `9 [2 \# {: u# J+ {
Offset 53Fh : 74h, 15h -> 90h, 90h
; G) F1 z; ^. G5 I
5 C* g3 a# a; V N3 j0 R 以上就是我们所需要的所有信息。
4 a" Z" F- X( j0 R) W7 ]9 l2 |
1 l Z6 |, q ?* x4、代码
$ K7 ~' C1 @) {
# }% F6 b$ B. i5 {* h- O( W$ f386
8 s6 o4 p0 s% ?; t O.model flat,stdcall
6 h1 g% D* k6 E& i+ N' k# V5 h$ xoption casemap:none & j3 h( x" F. A" @( z. X
include \masm32\include\windows.inc
7 K1 N7 [3 c! ]- kinclude \masm32\include\user32.inc6 o7 i' I% t4 a% |6 G9 B5 K, e& x
include \masm32\include\kernel32.inc2 e! L6 s5 _8 o5 `; U8 @ y. T
includelib \masm32\lib\user32.lib. y; |/ }. S1 ^% t
includelib \masm32\lib\kernel32.lib
8 d# j3 Q: z1 N* w% @6 z 4 S/ ^7 ]; w" T( L8 G
: ?% i2 x# g) n6 u$ V
.data
# L2 W$ `8 V5 S) d1 e9 T" Z+ o' fFileName db "Crackme5.exe",0: S/ |% M& c7 u- ~" Y5 ^
AppName db "Crackme 5 Patch",0
2 v7 U% P6 S, Z" t0 F0 b1 VDone db "File patched succesfully !",0
7 x& k# d8 X: s9 Q& q9 I" m4 LNoFile db "Can't find crackme5.exe !",0
7 c( J7 l# Z O r# ] hReFile db "Wrong version of crackme5.exe !",04 m: D3 C7 B, Q# I2 `* q7 N
WrFile db "Error writing to crackme5.exe !",0
( D4 p4 _" h$ z- q9 mRBuffer db 75h, 15h
; y% h8 g4 h5 C; G6 vWBuffer db 90h,90h
! j. `2 j# d- I2 L$ S+ f! B& ZOffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
5 S/ y' c- {2 B; b9 i4 f3 k" a" X
2 v- H+ w( [0 o; | x: V' ^% o.data?
$ V9 {" X$ m) j# S/ @' ?8 J2 Z y u! D. ]
hInstance HINSTANCE ?
/ {" y1 H$ p+ |" [! p% RCommandLine LPSTR ?9 T: a' O; B; j) i, h
hwndname HWND ?
! T. U1 I7 E, I! VhFile HANDLE ?2 R& Y& z& I7 y1 @. G6 H! X5 s
Numb dd ?. b; l& y/ O: [ U' x. l% H
Buffer db 2 dup(?) # \/ p! ~6 U, P4 Q5 S: S4 K
0 z; ^3 `* C9 G, [( `- x
5 H8 q5 ~9 @. s- Y; }.const) I h4 Q# p/ o' c
! U7 q6 u9 R% R; I3 o7 `.code3 N8 T0 X$ H( F
start:
' Z. S0 v: v) ^- R& F; l2 S( W# z+ A$ C0 y+ W
invoke GetModuleHandleA, NULL6 N5 @6 t* d% J. B# i- v7 [2 E; t
mov hInstance,eax " f- i" ~$ b$ W7 u
9 i, ^8 s3 C" C' kinvoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
/ Q7 K% W$ \' t/ q
. l/ a, P& ~2 s' |# Y' O.IF eax!=INVALID_HANDLE_VALUE9 A0 w/ {* s1 A4 q R
& |. w% C! y% a) }
mov hFile, eax ; 存储文件句柄$ P5 F+ R4 f. D+ V
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节
+ F1 S! U i9 X: T& ?6 qmov ax, word ptr [Buffer]
) P2 F3 w( P* y: n6 V: A.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)
: R7 r$ O" `2 m! S! l. `Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)$ q3 a7 b0 u- r0 _. `/ M
.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息1 `: O+ v6 q1 b/ w( |- @
push MB_OK
- T- v1 B' f! V7 v# spush OFFSET AppName
/ u# N& ]( _) |3 w: j* ypush OFFSET Done ; 弹出信息地址入栈
" }6 j8 F9 C0 p5 `7 y2 g; Y; I.ELSE ;如果返回值不是2,那么弹出错误信息
4 q6 Y v0 d3 zpush MB_OK OR MB_ICONINFORMATION& c) k H$ \" _+ `8 W
push OFFSET AppName
) U/ g, G& |. H0 D; s$ Gpush OFFSET WrFile& q! O5 @9 G; N' b+ x
.ENDIF
1 j F* e- Q5 _1 Z.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息
8 I _+ u! r4 M& i- m$ V8 jpush MB_OK OR MB_ICONINFORMATION
! [ T* m/ d& L& O& X2 Zpush OFFSET AppName
' q# Q' d9 x3 D/ C& r5 k3 j1 Wpush OFFSET ReFile
J3 @! V& H9 m7 Y( H+ M' s" s.ENDIF - @3 D, R" O2 W/ l; o" A. S
$ g$ c2 ?# E' E: h- N.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
0 G5 D6 G' W0 Mpush MB_OK OR MB_ICONINFORMATION5 r# D* A; d4 A. v
push OFFSET AppName
5 O7 ] @" {* s7 Y( Apush OFFSET NoFile
8 k4 ~" e |3 E" i2 y6 j$ u.ENDIF
0 S! q( u4 d; t. a4 K* }( S1 V3 ^, {% M+ H. V Y+ E- ~
push NULL6 U5 Q* d( Z+ E+ z# i- a8 E. ~# U
Call MessageBox/ k3 a h/ c \ }" ]1 O$ R
invoke CloseHandle, hFile ; 关闭文件
n+ y/ C% d$ ]5 q- ?% p/ l5 c1 xinvoke ExitProcess,eax ; 退出/ V: h* T/ M( U, Q U3 |: ]
5 `' j }) C6 H* n! Rend start7 D' }% C) ^ b
! w7 Z( c1 E5 V- c, {
如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。 & G0 c3 Z' ]6 \. L4 Q* p
# W6 K4 N4 K8 ~2 q4 p$ \2 i
var currentpos,timer;
6 a5 t1 t- e: N: G8 z( i* E- H @" A2 L8 ]: `6 ~0 f$ N& d
function initialize()6 a/ J0 A `# i' E4 _+ H5 O0 k
{
) t) o+ @ ]/ x; M) B8 K3 f! ftimer=setInterval("scrollwindow()",10);
8 Q& f0 K3 Z( x( r1 R% H- \}
, l2 u6 T E+ W/ B2 C6 d" A& Afunction sc(){
" S! d8 E! L- U# kclearInterval(timer);
2 ]+ x: D; J1 v( J$ `" w" [. ~}8 B% ~- o& P b4 R1 F
function scrollwindow()
0 f1 k% @0 _ u% x{" t9 H' m( O a' s7 }
currentpos=document.body.scrollTop;: y0 s/ n/ z3 e
window.scroll(0,++currentpos);5 E1 J/ I! S4 k/ Y7 W/ M
if (currentpos != document.body.scrollTop)
6 \3 W5 H6 D) G' N( q3 }sc();1 W* R+ W9 @3 o
}- w y! p7 q' T3 l$ Y* |8 s
document.onmousedown=sc, ~( s' V/ j( Z4 U$ a, d
document.ondblclick=initialize
9 z7 s+ p j% S& s( t8 |# m4 d
' V5 W* e1 O3 J2 W4 K, j( [, d# u) F ! _, x% a7 p! U! j6 v! w! P
|