|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友6 Y/ F. A; d3 d
会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助 . s% l" U1 e( T. S) ^* q
作者 : Detten Detten@tiscali.be ' z9 I7 \7 N" l4 P/ ]7 }
来源 : _blank>http://biw.rult.at/, n& n; f; F( g5 {3 Q2 `7 P0 `
1 q2 @" e5 Y2 Q翻译 : nbw _blank>http://www.vxer.com/
" I" z3 B, F2 D5 D
9 C5 G& B m. f. m0 }1、前言
/ O( T. T$ b) b* ^6 m8 ^ 一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
' v+ b( ]7 j' E ]7 ]2 V: i 那如何来写呢?
" s+ h* R" c8 U! q7 B5 c===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
' F4 `: }3 [ o- y; d) z" |2 O9 s v
===〉如果找到,打开该文件。
, q8 `; [ U; l9 j) K- g
; j) f8 s7 V( m4 M===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。
+ Q( V; X0 V9 T1 ^9 |) K1 h4 Q" ^& u/ @, b- E" @
===〉如果以上都无误,我们可以做需要调整
- x/ |9 X% {! {/ a6 W5 N 把文件指针移动到指定位置,然后写入新的操作码。
& v" t5 X$ `( j& Z& ?6 w
3 P! o3 N% ?) C8 D! f; i===〉关闭文件,给出提示结果。1 ^3 o3 a( [1 A
4 q, J" V. `. g% C8 R2 m
下面找一个你破解的文件,然后开始....
* q0 a ~, |& ~) e" F5 G
, ^& A3 \1 N) S; l' H2、必要的API$ r" e0 _) u2 {2 [; V% q
做这个程序需要用到什么API呢?
8 L' i# \; c$ w, E# |. _. E8 k
# _' {' n3 w1 o8 E+ oHANDLE CreateFile( , U& P' T2 l0 H
) g. H& ]0 b0 ]4 }
LPCTSTR lpFileName, // pointer to name of the file
; ^8 ~- H3 ^5 t8 H1 h- O$ eDWORD dwDesiredAccess, // access (read-write) mode
. ~: j: S+ H8 c% e- _7 k) K6 wDWORD dwShareMode, // share mode / }" d& @% z: [. a9 W
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
6 _7 q* }. h( JDWORD dwCreationDistribution, // how to create
6 y) L' B# R: U' p- a2 _DWORD dwFlagsAndAttributes, // file attributes ; o- M9 d6 V& Q# [
HANDLE hTemplateFile // handle to file with attributes to copy
) p/ u7 j/ I0 `/ I0 X, q);
7 ]8 Z3 C: ~/ A% c7 |, ]5 W& W& Z0 L) ~- P9 {/ ?
这个API函数用来打开或者创建文件。4 J# P) t9 |: E, l- i% `
dwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;/ I+ O. s1 N/ M b7 m3 q; n3 k
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'/ ?/ U) R6 O+ A2 u4 S% W K$ t
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。
, m% x. j+ s/ L 可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。( W' |" g# R! O- s! S0 p. y( p
如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。& A* @, w4 V+ X& c! c2 \3 z
* P7 e4 h5 P% zBOOL WriteFile( ( C; _5 ~: z+ s7 a/ Z
HANDLE hFile, // handle to file to write to
- A7 c X9 G7 B% NLPCVOID lpBuffer, // pointer to data to write to file F, ]( _; \% K1 \. g# U
DWORD nNumberOfBytesToWrite, // number of bytes to write $ _4 S: f: n9 o6 t
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
; Y: k# R5 S% D' k, V- LLPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O8 r. L+ b8 N7 z4 y- \4 \
);
" G4 \0 N) {' F( g2 u5 T- c: m' j# @" @* _ a; m: { i- t
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
: d1 h( R7 Y8 D/ H, A 涉及到的hFile句柄就是CreateFile函数的返回值。/ g8 M' _# Y+ g: f4 R x! V) Z
/ I$ d2 S" u8 ~: g! j7 { UlpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。! w+ C: @$ s3 S% ?$ q' ]; E
# `3 w- M7 ?) x: ?7 n/ f: b% `3 gtypedef struct _OVERLAPPED { // o
7 f d3 H+ g' D& d0 P U: ODWORD Internal;
4 K ~: F: T/ zDWORD InternalHigh; - ?2 B I$ c* T; ~2 Y4 L& U
DWORD Offset;
& j0 r" w: N& ^& }9 WDWORD OffsetHigh; / n3 m: ]# D0 |; c, ~
HANDLE hEvent;
1 Z) H- a* s8 I" r9 p0 X9 E} OVERLAPPED; 0 ^. ]9 E9 {0 X
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)
& \/ n! o' O1 i& v+ u
6 Q8 m7 A( k& J3、目标+ z% a1 l _* ]5 ]% ~' `, a$ L
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行)
% y4 K" `/ t1 R1 y+ |0 z% b2 | 当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:& {* [ q# }* z9 V* H" U
2 y, o" f5 F' oOffset 53Fh : 74h, 15h -> 90h, 90h
+ W0 f) r9 K$ k( X0 R" }8 B! w0 z. Q3 y" v6 Y; f, y
以上就是我们所需要的所有信息。
% p2 R- F9 |7 m7 M; x+ t6 R1 X- U* d) {' A
4、代码2 O4 z2 n/ e% E0 @$ e9 \
; {$ R8 f1 M( F* H9 @386
4 c; y) a% q' k* U+ ~/ l, j- \.model flat,stdcall8 S( I3 u% m5 U$ I" L
option casemap:none
& [" G0 c. N( X$ Iinclude \masm32\include\windows.inc( f! k3 `5 M- y) |
include \masm32\include\user32.inc
" }' e2 v0 g- ~/ `include \masm32\include\kernel32.inc$ ^9 I0 W0 x G# g2 E4 q7 O3 y o
includelib \masm32\lib\user32.lib
& ^6 {: y( @9 o, e( |) ]: _includelib \masm32\lib\kernel32.lib8 s! g1 S. Z: T. {; I R6 F0 ~
( e( ~5 f. C% q- J
5 [ ^% \2 c5 b% q( \.data
0 e9 n; w/ `7 t, T" r, X m7 EFileName db "Crackme5.exe",0; Y; T8 |# S/ U; ~' O: M3 A
AppName db "Crackme 5 Patch",0
4 ? w% k7 C0 O( l7 g# M3 uDone db "File patched succesfully !",00 U7 Q$ O j! N7 o( J! v; H: X
NoFile db "Can't find crackme5.exe !",0 W' A5 D# k; K. V' w3 M0 p
ReFile db "Wrong version of crackme5.exe !",0' ?2 |: B" H; R" P( K; F2 G% [
WrFile db "Error writing to crackme5.exe !",0+ \. C3 X, s4 Z+ y5 H5 g% [
RBuffer db 75h, 15h/ x( K/ J9 w {2 M7 F6 W" ?
WBuffer db 90h,90h. A, W2 N) P! h* x e6 r* q
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>
+ K" E$ t0 y1 l" F8 H `
2 o! S) r& Z. t4 p8 ~6 o3 D.data?
: f* M0 w$ O/ i. @2 \( z6 N; R$ [, _3 D5 S: `/ c
hInstance HINSTANCE ?9 a' D7 H+ J6 v& a0 q
CommandLine LPSTR ?
! a$ e7 V/ h/ rhwndname HWND ?
& u4 E: S" \) jhFile HANDLE ?
' a5 h! W' h1 a! G9 A/ ONumb dd ?
8 y6 x/ Q* x0 g/ }0 eBuffer db 2 dup(?)
# _5 a8 X/ c. n0 |' z8 A g- Z! L! q- z) e" Z4 P
8 b2 N* ~4 v* v( w& w% A
.const
) J# B# n+ M$ c/ @4 D+ @ : o* J# F$ R! {7 q& K
.code0 ^! o: w7 Z+ w* o0 G9 t1 L; C: a- ~
start:
( W2 X$ E. _, T$ j0 n; X8 @8 T$ @
% M8 R0 w$ y" c0 E; ~invoke GetModuleHandleA, NULL: L5 w' S! O2 z: [$ H
mov hInstance,eax
, ?4 O7 A% E& ?' m+ G! ?) C$ c( E0 F' F5 L
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL $ `) Y, F, e0 B& U1 d2 ^
- b, w3 U9 H- A' g7 y
.IF eax!=INVALID_HANDLE_VALUE
' s8 s% s g( t( i& N( E* `; W3 s$ h1 t' Y- `) Z
mov hFile, eax ; 存储文件句柄
) w9 `' G0 z* Q5 \+ m9 yInvoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节( H9 [7 n* d( v0 i( @/ c
mov ax, word ptr [Buffer]
& ]8 T. y) P) t, U4 h* U8 w.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)8 k* A$ u+ f3 W0 X: _
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
9 _" q1 f( R5 R- V.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
8 p; X/ Q' l9 A! F/ hpush MB_OK ; b Z; o& ], {9 j9 Q; } G
push OFFSET AppName
0 F) Y P, L& L3 Z8 u7 |7 g: {! U" Cpush OFFSET Done ; 弹出信息地址入栈
3 ]3 S. y/ O- e2 Q7 }.ELSE ;如果返回值不是2,那么弹出错误信息
: a, _% |! C# u3 n0 gpush MB_OK OR MB_ICONINFORMATION5 S% G$ @9 F' A, }+ C
push OFFSET AppName; O% Z2 x' F) g2 X6 A* d; T
push OFFSET WrFile1 G3 H8 S( k, k
.ENDIF
2 S' X: X; @( |* @* ?.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息: G0 Q% K. q5 R2 S" N e
push MB_OK OR MB_ICONINFORMATION
8 V" Z2 r) e+ t+ A- Cpush OFFSET AppName
# q6 m3 a }: J, m" J4 jpush OFFSET ReFile ' J, r3 p# _! F4 r3 \+ d
.ENDIF 6 S9 {' l! t1 H# S& B
' Z: V/ q5 M5 R2 N
.ELSE ; 如果未获得文件句柄,弹出文件不存在信息3 D% y2 D* H( Q: F: Z
push MB_OK OR MB_ICONINFORMATION
9 y! ]4 j# }1 A& Q U j0 T9 epush OFFSET AppName( s. @5 r! R# q- [3 _
push OFFSET NoFile 4 e% o7 l% q6 q v5 M4 a8 S
.ENDIF
% {: X. w1 P2 E$ X5 V& g1 I, c
push NULL! X% n6 _) d& v. y
Call MessageBox8 {& V) X0 I+ h' ^* o$ s9 x v
invoke CloseHandle, hFile ; 关闭文件
7 R9 m4 h* ]! ^" t$ Z" j- `invoke ExitProcess,eax ; 退出
4 K5 p, P7 R2 v7 I$ w# W5 Y
$ I. _8 s/ g3 v0 ^4 K) W; jend start+ A, l* r' ^* |2 F: t. |
: P9 Z8 T2 S5 l( F3 A. Z; A
如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。 6 g$ @7 k' A: a$ S+ Z
' V# B; L0 g8 K1 f
var currentpos,timer;
. e3 Y- \( l' R8 g2 S/ a8 K. E3 j' ?* c3 j0 \9 x
function initialize()2 f- }* T1 a9 H8 w% H
{
7 Q ]4 Z0 E6 W% y9 c6 ~& ttimer=setInterval("scrollwindow()",10);& r% o0 l0 ?1 K( ^* _' X
}
T9 p! e: O/ l7 h5 Efunction sc(){
+ J" C% G' Y% w1 W7 q% ^clearInterval(timer);
# o: {$ |7 g0 N/ @) R, I}( v7 F5 K; g! d9 W2 t& ?2 x
function scrollwindow()
/ ^, _4 }. K$ W; u# S{
) w% I7 i5 U }5 a& }: u: jcurrentpos=document.body.scrollTop;( f; U6 }6 J7 `, q
window.scroll(0,++currentpos);
- p& X+ k8 M) V8 F3 @1 I! x2 Wif (currentpos != document.body.scrollTop)6 d% q/ h( s0 U) n- T
sc();
1 V9 I4 m) I+ T. A2 Q1 H+ w" l4 R* u}3 \+ h* m: w/ S; Y$ y) ?- \
document.onmousedown=sc. T$ x. n7 _% i8 k4 x
document.ondblclick=initialize
6 w% H0 ^( A a: X `0 k$ ~ `6 ~, |3 N5 \8 N' _: [
9 |' c7 i. V' ]2 J' r" E
|