|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友8 ]/ \/ {* o* ~* [; N o& _3 _
会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助 9 O& P, z( q B( N0 T
作者 : Detten Detten@tiscali.be ! x& m5 Q9 f4 B1 ]. w
来源 : _blank>http://biw.rult.at/
$ h6 z; O# i) M0 v6 N$ s; R
+ J8 Q2 I+ R% b: r: Y翻译 : nbw _blank>http://www.vxer.com/
+ y; U9 m2 I1 t: k; P* I- ?
: A# b1 Q0 \6 ]# H6 N' ^# C! B1、前言
7 z9 L+ g$ N) C9 o R 一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。9 Q' `$ J& l0 p# X! ?
那如何来写呢?
0 K+ m2 c4 i C6 I0 t, x===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
7 M3 G6 d; S9 w# T$ i( `: x/ E1 H6 B# K# H- H/ u$ |
===〉如果找到,打开该文件。
. o8 L* J" ?. L: {: K) ~" T$ v2 f, }; p
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。
4 t' h& \+ |/ k v; w! Y( R9 s. B6 E3 E7 V1 T" L5 g
===〉如果以上都无误,我们可以做需要调整
1 K; L/ Y4 i; A1 U7 P, ` 把文件指针移动到指定位置,然后写入新的操作码。
# A6 X) K8 U6 C9 e6 R6 _, s+ H3 `0 p
===〉关闭文件,给出提示结果。4 i- `* N7 U1 l9 C
$ a6 d0 S0 |4 Z+ A
下面找一个你破解的文件,然后开始....7 K9 A; W, n0 V/ e0 k# d& t n' i
' L2 M+ i% e. W0 k1 T* r& r$ q
2、必要的API
9 O2 j% w% ]0 }4 v+ M 做这个程序需要用到什么API呢?( a7 ]4 V" }' ~# L' }7 W; }. T
8 Z) H; C; T3 J! d' C* THANDLE CreateFile(
5 x# |& x7 W9 e$ F
4 K0 W F% \4 i, l* iLPCTSTR lpFileName, // pointer to name of the file
6 G" P* e% E' D3 i3 E: g: q; SDWORD dwDesiredAccess, // access (read-write) mode ) ^' N3 V4 e, H9 _8 G! U
DWORD dwShareMode, // share mode
* R/ B8 y0 @# K4 xLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes 3 C( x2 v9 k7 c$ a/ I6 W! E7 `3 A k
DWORD dwCreationDistribution, // how to create 1 Y: w' p$ P9 c+ M& ]
DWORD dwFlagsAndAttributes, // file attributes
5 N* N( |* r3 {- x) cHANDLE hTemplateFile // handle to file with attributes to copy 4 e* K- [* d; k) W: e- ]5 L: K" K4 U
);
0 Q- [/ c Z4 [6 [; K, K5 j) ~( h: h3 j( h% T7 H
这个API函数用来打开或者创建文件。
* C c3 [+ e v) `% g" f1 {- ndwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;6 K9 k5 s S" O1 T( j
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'6 J7 y- k' ]# E- A
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。( }' {( M L( W. ?$ K& c9 D
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。
1 E+ z0 b- K5 B- b4 Q9 P+ r% h 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。
8 L) \/ k$ Q B* [* i6 \ v) i1 A( K- e: r) j$ c2 X
BOOL WriteFile( 2 W& T( @+ I0 I
HANDLE hFile, // handle to file to write to 0 c1 G3 ^1 @: m" Y* [
LPCVOID lpBuffer, // pointer to data to write to file ; |- l" P1 s6 P9 T0 O
DWORD nNumberOfBytesToWrite, // number of bytes to write
3 b. _' R m: @$ r( L7 b9 ~" OLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written 2 {& M' i/ o0 v/ j) h
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O( [7 U+ S- K K( O% c
);/ F5 T7 x# [6 L; X1 r
3 z' k, L) [; K9 N
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
( @ m' g$ g; q( x 涉及到的hFile句柄就是CreateFile函数的返回值。
" U8 a! Q& K; s
4 u( Z( E$ {# I: j3 y) x! f# [lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。5 w" W1 T P. n0 O% n2 p
, M$ x/ z% J. ~# P9 `% [3 b
typedef struct _OVERLAPPED { // o 4 Y+ s& E1 q0 l, s! R& c
DWORD Internal;
?6 J9 N% G+ IDWORD InternalHigh; 7 R% `3 z8 m! W; w& M- ^5 O
DWORD Offset; 5 Y5 F2 t) g9 ~, E* p3 {! v
DWORD OffsetHigh;
& G9 O& m2 Q5 y* I% MHANDLE hEvent; 2 o/ |! v! F: t: n
} OVERLAPPED; ! c7 E2 G( g' a6 R
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)+ |( l+ b; r" {; A; \, L( ]
4 G: R- N/ M! J" b9 K3、目标
6 s8 E$ o) s1 V% [: Z" L 目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行)
5 K) c7 u# e( w# ]' Z9 d4 z( O 当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:. \- K: a6 p% Y% r$ h8 M
/ ?# f9 R! O9 p/ hOffset 53Fh : 74h, 15h -> 90h, 90h
: H" ] S4 B2 s
* ~# M9 }5 s+ ?: D3 U7 a; I 以上就是我们所需要的所有信息。
; i6 C; Z* N& s# Z3 a+ Q5 z+ c! R3 S: h T
4、代码
' a5 E/ K7 o2 C; n$ {0 h
% i# ?- T9 n$ s- P8 K0 b l! U386
5 b& L8 C; E5 |3 T+ k7 e.model flat,stdcall
: G) e# _ X5 R- z6 T7 zoption casemap:none , L$ h- I5 Y' ?1 Q4 k7 @/ h' g! { ]
include \masm32\include\windows.inc
* N! G1 P& L9 \& ~$ Dinclude \masm32\include\user32.inc
+ I. D1 U* E3 J' Iinclude \masm32\include\kernel32.inc
2 |4 ~5 \* E" ]9 C, t# y% Pincludelib \masm32\lib\user32.lib2 D/ b l4 ^. w C3 G! K2 c
includelib \masm32\lib\kernel32.lib
" r% w9 T' s5 B
7 t- X) H+ n- A; C( w4 Q/ d3 v3 w8 j
.data - g' d" }" I' E5 S: D0 |6 L9 h
FileName db "Crackme5.exe",0' V9 B! K3 y( b/ P
AppName db "Crackme 5 Patch",0+ ^3 F( q8 X! e- z8 X P9 N0 h i
Done db "File patched succesfully !",0
7 }% n6 w) D5 j7 g7 vNoFile db "Can't find crackme5.exe !",0# S4 i2 _4 {* q
ReFile db "Wrong version of crackme5.exe !",0
( ]; [8 k6 q p. j+ o, R' H' EWrFile db "Error writing to crackme5.exe !",0
2 ~3 L( b+ K6 ] R' S/ iRBuffer db 75h, 15h; M4 h" f6 z! w8 `0 A9 Z B1 `2 q" M
WBuffer db 90h,90h2 m, B3 Z! n3 I8 e
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL> # L1 J/ Y% _/ {
i" G5 B C$ @8 W0 p& Q' N.data?3 W6 \, `( O9 T' c
- G L- A1 |/ S0 p
hInstance HINSTANCE ?1 l; s; D5 v6 t7 W, p, _
CommandLine LPSTR ?
# V- L, v/ x, m* R7 |$ l" ?% g& qhwndname HWND ?& R! y) e+ _+ I1 R( t
hFile HANDLE ?1 p! \; l7 d7 u8 k. P8 \
Numb dd ?4 w# Y" T% _. T! V0 F/ ~' ?
Buffer db 2 dup(?)
# n" J2 d& o# V: b1 I
- a9 j. D' q# Y* x6 D
& H F( b8 y( X/ U: B! C3 ?.const: Q6 W1 u# r7 ^; {+ Z2 S7 t/ ]
* a0 g [+ [! N9 g" t) H, v.code! X6 G9 J8 [; F
start:
7 Q: j: p4 R6 P# |: N7 O0 ^# ]" z
invoke GetModuleHandleA, NULL
4 }+ [! i/ L0 m) J/ H- \5 ]mov hInstance,eax / L7 [. M- ^$ H
* g# z( l* R) L- n1 g: H
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ( [* s0 {' ^: o/ Y
9 [% m+ O: W. }.IF eax!=INVALID_HANDLE_VALUE2 z/ L5 v- |2 A) P; p2 a& j) a' S
( W% Q- _ g B( i- v# H. k
mov hFile, eax ; 存储文件句柄0 R; G+ j8 v3 l9 y1 R; E6 j
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节* q1 t7 \. o, _) _1 Y
mov ax, word ptr [Buffer] ) }# t3 Z; I/ \
.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)' z0 T/ l1 z' t! o: I; k) ^
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
; V% q0 \+ M7 H.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
$ z8 k+ U0 U* U" tpush MB_OK $ [. v5 {3 j" d A7 ~2 ~* R
push OFFSET AppName
" E* w$ [* s. r8 r7 t6 s9 q7 qpush OFFSET Done ; 弹出信息地址入栈
9 \2 K t+ B6 G8 g# @) a! s.ELSE ;如果返回值不是2,那么弹出错误信息 c; ^3 Q* a5 f! X2 N* |& s/ U7 y
push MB_OK OR MB_ICONINFORMATION1 V1 P5 F! h% k" S
push OFFSET AppName
8 S1 @1 D; g) ^+ [9 _push OFFSET WrFile! v9 R% K! G0 U. m1 r' o8 d7 U
.ENDIF
$ {' l# e5 z( R0 P/ G8 [8 H- H7 r% S.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息
: P) w3 C; u6 C: r3 F, ^- spush MB_OK OR MB_ICONINFORMATION
# M( m* K6 |. l2 b s+ Cpush OFFSET AppName
+ E4 ^" C4 R# P q4 ipush OFFSET ReFile
* m) S% t$ j: u7 Z.ENDIF
( j' U$ ~2 u/ W" }) ~! B& }* s# \4 p. A
.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
, |3 C4 S/ W* qpush MB_OK OR MB_ICONINFORMATION4 G6 b! I) x7 N8 a+ o" W; F: X2 l
push OFFSET AppName
8 J% l! C; X5 W' M* O) u: Kpush OFFSET NoFile ( X$ m0 t% q5 o/ ~0 S2 Q+ l
.ENDIF: W* F; I: T1 G4 `& y; R3 S$ n4 V
/ l+ x. z' a2 w
push NULL
1 ^3 w; L. Z$ O6 d+ C6 l+ E: uCall MessageBox% ~7 H7 {' [, N7 |% k4 W
invoke CloseHandle, hFile ; 关闭文件 X) L8 ]+ \. v
invoke ExitProcess,eax ; 退出
1 Q3 B( f4 O9 d3 f6 ~+ G. C% C+ P+ s. ~6 y! V, t& f
end start' w1 t7 J; T8 u6 a
7 s5 X4 j% K- z& j& t a" H 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。 2 f% H; t) p7 K( D
$ M+ I; n, k3 D) F( m# Rvar currentpos,timer;
# v0 Z w1 B: X V5 W- I5 P9 `; X# R3 ^+ f' ^# F5 q
function initialize()) B0 j. ^9 Z% q. C. L" T$ Y$ a
{
3 s9 K+ k1 n6 ` Mtimer=setInterval("scrollwindow()",10);* y9 {5 Z$ v ]' u* `1 R! @5 @
}
$ `- x. T+ w' G5 b0 x, Z- vfunction sc(){
3 v J3 }3 Z. _3 f1 z) @2 S' V' HclearInterval(timer);+ [" R0 ^' y% t5 a/ _0 n
}
: D5 z/ ?8 ~' {function scrollwindow()
( S, p2 e- |" j9 b# R/ l& X! c{% Y4 I0 I2 I/ b) H6 Z
currentpos=document.body.scrollTop;
! y. o2 }. o4 \- nwindow.scroll(0,++currentpos);% J6 N" v2 Q/ Y* ~( W8 T2 Y
if (currentpos != document.body.scrollTop)3 ?4 s) o2 n$ @# Z% q" ]1 A2 m+ H: d
sc();
# L$ N( H& Q. e M$ p% t# M" u2 X}2 I, `' E: d, f* u; k3 K
document.onmousedown=sc2 D, Y: V2 d) G( t1 g& H
document.ondblclick=initialize
( G6 x' @4 h* u0 Z4 c# }
4 J! b& i+ |8 X
: k3 D1 b) F5 ^# K6 x |