|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友
1 d- x: a7 a% i3 i会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助
$ O+ C" u& r8 }) ]作者 : Detten Detten@tiscali.be 3 M( _& w, u- L; x+ L8 X
来源 : _blank>http://biw.rult.at/0 n( d. K/ E9 ?
: |) ^. `3 t5 V) [6 ~6 e
翻译 : nbw _blank>http://www.vxer.com/5 I- @$ q; p# R% `3 K
, _( P6 ^1 r( z; G W1、前言- d+ T v3 w. n9 ?- Q" l
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
$ y# p% j c' V" d5 Z2 Z3 p 那如何来写呢?
- q3 {& J9 g; ]7 T0 ?6 I===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
3 n% F9 i0 L" F4 y5 q7 R- W; x7 K
===〉如果找到,打开该文件。
/ ~" t% K1 ^/ e, E; _+ F. p: ?# j& F5 H' ^. l! w0 k
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。4 z/ f2 a, _2 M5 M- B
9 D- t, Y4 H+ N! I0 ^===〉如果以上都无误,我们可以做需要调整
3 \, n: j" B$ B" u- \7 g) ^ 把文件指针移动到指定位置,然后写入新的操作码。. f Q: ~* J; h/ N6 A5 c
7 ?7 T K- @* A G; _===〉关闭文件,给出提示结果。
' n; l) G& I. q" N! f8 X: U* W- `+ r7 R5 P
下面找一个你破解的文件,然后开始....
% u6 ~9 x$ \1 M8 H5 @
! T+ B! U- C6 U& c2、必要的API$ ?' H: J6 _+ h4 T
做这个程序需要用到什么API呢?
( I# Y6 P. P7 N4 O6 a
6 k% h9 ^- p+ X, }$ ZHANDLE CreateFile(
" H8 q/ n, u! T# v O. e9 y( A3 ~. q! o
LPCTSTR lpFileName, // pointer to name of the file
0 j, n9 x P( G! s% |* _% XDWORD dwDesiredAccess, // access (read-write) mode / R3 L; D' C8 o6 o3 m
DWORD dwShareMode, // share mode 5 W X! O( |4 z( H0 ?" Q1 p
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
+ M3 N) _4 Y5 d& wDWORD dwCreationDistribution, // how to create ' \7 i0 \/ S0 A. y
DWORD dwFlagsAndAttributes, // file attributes 8 v) ?/ T8 e7 I
HANDLE hTemplateFile // handle to file with attributes to copy
5 o* s0 H$ X- J8 \9 E);
3 Z% ^- Q. i4 f5 D
1 H$ B/ ]8 D; X- R 这个API函数用来打开或者创建文件。
* I6 s2 h5 V4 |: XdwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;6 E0 b3 T0 X n7 C" B9 r* p7 {. g
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'" S- z# o4 E6 B
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。
2 Z1 n/ ~) u2 h2 e k7 W {# h. Z 可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。: |. w1 @ w; }& F+ T1 H/ D! [
如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。, x* _* D2 z+ V$ w" H* @+ j( u: Y
( U) q: ~8 q1 ^9 W) _% w- T
BOOL WriteFile( ' g" E# o9 }/ W1 l6 H4 _
HANDLE hFile, // handle to file to write to # q& L5 m, D) x( |( I% T
LPCVOID lpBuffer, // pointer to data to write to file
% d4 X1 b9 z" S. QDWORD nNumberOfBytesToWrite, // number of bytes to write ! N4 e9 B- d2 | t
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written + f9 r& g& c. f
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O% L7 J( W3 a. |8 M; {& _
);
( M0 F' ]6 v$ M( J- u9 N9 r9 M4 W! m* Q1 \0 r8 I5 S
我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
0 y1 D2 x0 Y4 B 涉及到的hFile句柄就是CreateFile函数的返回值。
& d, `% t7 ?. g$ t5 Z' T* ?8 J
! C* y; H0 e2 S% R( _5 NlpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。
7 E+ z; @# z5 G% e$ U4 K( ^. o" R# a; i% s; R
typedef struct _OVERLAPPED { // o 8 ^. U; K$ u4 ~- W" x
DWORD Internal; # z1 X. c1 Z9 |4 L, a/ I q4 W
DWORD InternalHigh;
! u, l: L7 U, r6 s3 D+ x0 ODWORD Offset;
7 `0 ^. O6 u9 a1 W0 `3 D1 ~DWORD OffsetHigh; + E" q8 T2 ` q
HANDLE hEvent;
* {9 _! U9 X6 I& _, Y7 P& _} OVERLAPPED; ! u# x0 H0 l, v8 {$ o
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址). G' F: V8 V# A* k; Z
1 n7 l! Q7 R! D3 X( D
3、目标( z6 F7 C' g( z8 K2 D/ m
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) 8 E0 f) P% X( u1 |% I
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:
, D) l: @6 s1 q5 o7 u1 E; m1 [, y U: l7 r$ n+ o2 Z
Offset 53Fh : 74h, 15h -> 90h, 90h5 V9 G; j/ `; n/ ~8 M
0 z, v8 }6 u7 |+ \. @2 y
以上就是我们所需要的所有信息。9 h+ S0 @# U5 f
7 C; j3 L/ T& [$ U" B H4、代码
5 ]0 h, U. x+ e. z
^0 F+ j4 G3 Z6 Y q; V. h386; U5 V# j& R' Z% M: u
.model flat,stdcall
" [1 S2 M9 Z9 |% B( e; e. \8 z5 `option casemap:none
( d; y! U/ |! Sinclude \masm32\include\windows.inc
& N5 N. I. `+ B% winclude \masm32\include\user32.inc
( x# ~8 I. D4 C1 \9 X+ f+ `% ?) |include \masm32\include\kernel32.inc: K4 G2 D* P7 ]6 c$ j7 E" u
includelib \masm32\lib\user32.lib+ B, y1 T$ S& c3 F7 y; M# T
includelib \masm32\lib\kernel32.lib
- Q1 W8 N( S$ _9 L % V8 b* H. X0 s/ V( t1 A6 f
2 q+ U/ Y' U. b
.data
* i+ c9 b, w; T! t0 OFileName db "Crackme5.exe",0
( E% i# p% \" y5 r! E5 w7 yAppName db "Crackme 5 Patch",0. m7 s: E! x/ F9 E
Done db "File patched succesfully !",0
. T4 w3 |" H0 I# H6 WNoFile db "Can't find crackme5.exe !",0' t: D6 ]/ f0 M1 g4 q
ReFile db "Wrong version of crackme5.exe !",0' h5 _& h, x8 \5 X& a6 [
WrFile db "Error writing to crackme5.exe !",0
% Y2 R- n0 J& cRBuffer db 75h, 15h- p( t( n( O' ^
WBuffer db 90h,90h( [7 U4 E7 M4 J6 v/ s& _
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL> 3 I: s/ ~2 d- B
4 ]0 ]% F% s( _$ x
.data?6 n5 [5 _0 W3 h: b' \; K# R% c' V& S |! H
- [* h2 V& e' U: M
hInstance HINSTANCE ?
6 v2 y: I8 E: r# e$ [9 k- XCommandLine LPSTR ?
4 ^2 j0 }$ i* }9 a) Z$ _& Fhwndname HWND ?7 }$ H3 U( ~) R' Q8 @1 h5 l
hFile HANDLE ?
" t' U) y( s1 {2 V4 J0 u& `Numb dd ?( x) P3 ?! Z7 e0 N/ s7 A% L3 v
Buffer db 2 dup(?) - L' E9 P k) [- u6 |( R" L ^6 x. B
! F- C$ j, \0 q8 c8 ^6 q1 y
9 _. o- C( y3 ~0 U* y3 P
.const
0 o2 o7 n9 L% Q( Q) M0 ^
* b; F$ ?4 q" G, @; }.code
" i, K/ Q- }0 z# Fstart:* `# x& |; J5 o d, N! P2 E
, {" Y" D: ^# p: winvoke GetModuleHandleA, NULL
' C9 \7 F/ N% Z) p( p" ^mov hInstance,eax
0 _! d. t# o2 }# }, a
# m4 M' `# q: N7 `, h7 F) @' Ginvoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
4 v' d5 P5 i* _) J e5 G3 L/ r; v2 _/ f, [5 O
.IF eax!=INVALID_HANDLE_VALUE- D3 y% g5 F+ ]% ]2 P5 |, K
9 Q# K0 L6 P% d: i6 c' Wmov hFile, eax ; 存储文件句柄
3 F# g# T/ g( m: J0 IInvoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节
6 ]5 M: L2 C9 _- Imov ax, word ptr [Buffer]
1 r- F" Z: l: {+ f6 `# W0 Z+ v.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)7 e9 V6 E5 t. h7 V6 \" p
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
/ X3 k1 a6 E' { }1 p1 X.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
& U( y9 d0 v8 B! V) @6 U( l2 M! ~push MB_OK
1 O- M/ ~/ b4 e1 `& vpush OFFSET AppName
2 p( q# G$ p% C+ hpush OFFSET Done ; 弹出信息地址入栈
4 j, Y3 W7 L: j0 e.ELSE ;如果返回值不是2,那么弹出错误信息
5 I( }9 g0 `, U V8 R2 Ppush MB_OK OR MB_ICONINFORMATION) x) U& }7 J" e
push OFFSET AppName4 y( Q9 w0 s: S; S" p6 Y
push OFFSET WrFile
' f1 r( L; w9 l, W.ENDIF 4 ^- Y, c& P7 e9 }/ T" T* w
.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息
5 K6 j$ v) \/ Ypush MB_OK OR MB_ICONINFORMATION
0 X+ R, @0 b6 o7 n1 Ypush OFFSET AppName8 M+ {! n3 P$ ^$ S1 [# q
push OFFSET ReFile
8 M/ {! e8 x( `* {) l.ENDIF
: v0 D( ]$ B* I& D$ d$ n
& g: F. Y$ w2 ]* ^" }, g.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
1 Z# h J0 ?4 _ o# ?, \push MB_OK OR MB_ICONINFORMATION
" ^& x8 ~0 d3 [; W8 _" ?7 j( Dpush OFFSET AppName
. ~0 W/ a: ~. V& [8 g1 lpush OFFSET NoFile
2 p+ g* ~0 q' r' L" z6 z: I.ENDIF
- n4 e/ G. L) m6 P9 O8 p/ o1 C5 U% v7 x. ~$ J! t9 q: u
push NULL1 u" m4 v* z7 K; w- Q( m. i
Call MessageBox$ T, c( b: c- K& B! H. R% i
invoke CloseHandle, hFile ; 关闭文件1 l0 Y) C& N9 }: o" D
invoke ExitProcess,eax ; 退出
" d; H3 e" ~# t2 x
6 q4 { G8 G0 v- Z1 L# L, nend start
# H/ w8 }7 R; }, Z- @/ X* s
7 C% w! j" O% d 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。
7 X8 K( g) V {, q6 Z
6 r3 o" ? I/ g0 Gvar currentpos,timer;
( y1 F/ B8 g$ y1 H
% j& e. D% }1 j6 r$ U' {# A% Z: p5 S* ffunction initialize()
( g) b& g3 m# d, m* y$ ]{
. P4 X3 S3 n' _, T2 W' s) ttimer=setInterval("scrollwindow()",10);* e8 J: W5 I/ ^( F
}8 _# a( P0 s o3 n) V( T
function sc(){
9 v9 o, S1 x6 y+ [: [( b" EclearInterval(timer);
# Q* A* h) @1 r# o& P}# [. Y! r8 e: ?2 M3 c2 C$ @6 X
function scrollwindow()
- S# `2 D: K5 } a6 I{
$ Z8 F1 E( x8 D) ~( r/ P* Hcurrentpos=document.body.scrollTop;3 s$ K( O* }, t1 N& x; V
window.scroll(0,++currentpos);, B0 }& v0 @3 N1 F% U9 x' V. x, w4 L
if (currentpos != document.body.scrollTop)8 d" ]. }2 `9 A4 Q& d
sc();0 w5 k) ]7 t6 ^) [+ I
}+ |2 _2 E2 t \1 U! g# q. b- m% Y
document.onmousedown=sc+ y6 @, n; A; K! g$ p- `- ^
document.ondblclick=initialize
9 z, V0 v; G: E( B
^' t+ Y, G# r1 a7 r4 d0 x + k7 ]; i; D R o6 G4 h
|