|
编者:昨天一个叫aqtata的朋友发给我了个最新的密界文集, 本来想打包下载,可那样很多朋友
9 T0 [9 c9 ^& ]. j+ y会看不到里面的好文章.于是我决定把其中较浅显通俗的一些文章发到文章区,希望能对您有所帮助 - A# g5 P' K5 o( t9 U( D
作者 : Detten Detten@tiscali.be * `& y9 g8 N3 @* t- F$ M# D8 r& C D
来源 : _blank>http://biw.rult.at/; o# e6 m6 V; c, n; k9 M* F
& ?+ D# ^$ I& C
翻译 : nbw _blank>http://www.vxer.com/
8 J$ |$ E3 ]$ S j
; Z ]& A9 r' l; m5 c2 C1、前言+ T0 f U b' B- `% S( \/ P
一但破解了一个程序,你就想把成果共享给别人。为了不用把整个破解后的程序上传,你可以制作一个小补丁来修改程序中必要的字节。
, H+ h/ b! W( I2 f 那如何来写呢?
2 h2 F) g; ]: | Y===〉首先找到需要打补丁的文件。大多数补丁认为该文件处在自己当前目录下。
& O% y! R" ?1 c+ E
4 |% `# y3 J+ v w& w8 ^5 E( _) m===〉如果找到,打开该文件。
) h2 B& T, o2 Y( k5 Y4 \% _( O; R( c, D' h5 [
===〉然后检查打开的文件是不是和所破解的文件。比如我们可以检查文件大小,或者随机检查一些字节,或者最好检查将要被修改的字节。
- j4 K9 ^& p" r6 }. Z8 u' P, p9 F
===〉如果以上都无误,我们可以做需要调整
6 F: I' q* q1 M% i 把文件指针移动到指定位置,然后写入新的操作码。
) _) H1 q U$ V4 C( P& b9 d: o
$ B+ Z" y7 e3 B2 D9 l# I===〉关闭文件,给出提示结果。
9 j0 J( C: N) m) I; r) }6 ~: ?( p1 R
下面找一个你破解的文件,然后开始....2 }6 V/ z3 r2 ~ D8 \4 z$ ?4 ~0 l
% x) y' u2 @- a( t2、必要的API
. z8 ~2 F, G5 w3 O 做这个程序需要用到什么API呢?
0 X6 z$ w; C$ R8 f# C- m% \' t: O
+ b5 ] v% q7 Q( i+ i) ]( _& PHANDLE CreateFile(
, G6 Q. {" }% e4 G0 N) R% l" V1 i( [4 q& D* W4 m
LPCTSTR lpFileName, // pointer to name of the file
) m) P$ d- k* KDWORD dwDesiredAccess, // access (read-write) mode
1 F1 _2 T. w' }: Q A$ e# zDWORD dwShareMode, // share mode
2 R; |% O# r0 GLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
4 Z4 W$ f4 A( ]! D$ I, |& ADWORD dwCreationDistribution, // how to create
& A& i9 l$ y5 fDWORD dwFlagsAndAttributes, // file attributes
) Q8 r! y$ F5 r2 V* j- yHANDLE hTemplateFile // handle to file with attributes to copy
1 }" g; H* b) `. h);3 f1 D4 y" g8 I- S# n
( }2 p6 |* w! l1 w+ h3 Z 这个API函数用来打开或者创建文件。
8 ~/ O7 V. Y, l/ d- adwDesiredAccess 应该设置为: 'GENERIC_WRITE OR GENERIC_READ' ,因为需要读写文件;
9 G- {6 q3 [6 K* k G/ d1 sdwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'" K: ?( V/ p) E7 G4 d. o
dwCreationDistribution = 'OPEN_EXISTING' 我们只需要打开文件,如果文件不存在函数将返回失败,然后我们给出提示信息。% g) W2 r: }( H- O# Z
可以察看WIN32.HLP获取详细信息,如果你没有这个API库,可以找相关资料。
; G4 N0 c! k9 y- u 如你所见,这个API函数返回我们需要文件句柄。我们可以利用这个句柄做下一步:写文件。9 I" h: F2 u$ r( C, v
* ?) c6 c2 a* y: c5 W8 W" V+ UBOOL WriteFile(
" A$ I% v; x* r! p: G0 CHANDLE hFile, // handle to file to write to : _7 ? P7 }* y- T
LPCVOID lpBuffer, // pointer to data to write to file ' y) W5 Y+ F2 w9 r# S; x
DWORD nNumberOfBytesToWrite, // number of bytes to write
# U/ i' F1 [4 gLPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written $ S. O ^( B: H
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O6 i5 H: I) M; c* H5 {9 _! F
);& ], O) R+ J1 ]+ [1 a
6 \& u% e1 y( |3 ~: t& {: t 我们用这个函数把2个字节写入需要打补丁的文件(当然是在正确的位置)[译者:作者的例子是写2个字节,我们做的时候根据需要]
0 S1 u3 S, J; F& V) ? 涉及到的hFile句柄就是CreateFile函数的返回值。, v" f0 v2 {2 i, L# d3 {
3 \( [6 R7 b3 p5 `( a/ ]
lpOverlapped应该指向一个 OVERLAPPED 结构,我们需要用它设定正确的文件指针。* V3 [/ g" Z- |* Q) L- H0 P
% v Q5 c, W1 h$ W% I0 rtypedef struct _OVERLAPPED { // o
4 _9 [, [; ?/ w5 p2 s; uDWORD Internal; ( m' {1 q: e& X- b7 n$ u
DWORD InternalHigh; 2 H0 j, f t* u+ `7 o5 Z$ Q" T
DWORD Offset;
, B4 t- e' c: q9 o K: w( EDWORD OffsetHigh; `" Y9 R4 `5 V) X+ O5 E% y5 g
HANDLE hEvent;
1 ?3 ?) v) d3 t3 b} OVERLAPPED; 9 `1 u) u- t1 B3 Y+ L E
Offset的内容是需要写入的地址。(译者:注意不是内存中的虚拟地址)
9 w# h8 o: _+ P( x+ }
6 C2 S( A/ N5 l3、目标4 [) E6 H" R0 S% j' E) x
目标程序是Crackme5.exe,假定我们现在获取不到正确的序列号,而需要对他打补丁(译者:这个程序我也没有,大家知道意思就行) ) [" p1 B7 Y; @3 Y R" Y: W
当然你肯定是不错的Cracker 并且很快找出来了需要修补的地方:
/ I! M, z* Z2 l5 A& T
/ T7 y, H1 J- T8 m WOffset 53Fh : 74h, 15h -> 90h, 90h4 _4 N2 n3 j; H5 e V
! v6 d$ {: k$ @# b W( W. i 以上就是我们所需要的所有信息。
4 ?" P$ u$ G0 d, S; h/ {
. L$ C6 i* i |. ~4、代码* U7 S& { K& b* w7 _. ]
+ Y+ i8 E/ N/ V7 A! y- M2 ]) X386$ d. G& r( h+ o
.model flat,stdcall
4 r5 b( Y# c+ K2 [$ _! _* {option casemap:none ) @+ S# N2 j# _! x; Y
include \masm32\include\windows.inc" V$ Y+ {) H4 o: _
include \masm32\include\user32.inc
7 Y0 M7 g- A5 B {( ^' ~) }include \masm32\include\kernel32.inc
6 I4 V; d4 ^0 K$ M; D; b rincludelib \masm32\lib\user32.lib, P* j; [3 f* A7 }2 b
includelib \masm32\lib\kernel32.lib
/ `. F& A/ K+ D $ L8 b3 f: v& f* O! W$ Y! c* |6 B
! ]: m$ U' Y0 `' ~8 B0 R( }# Z0 ^.data
3 u; C5 z; ~( A3 L, N! Q0 ?0 \FileName db "Crackme5.exe",0* W+ M; k; s. k. S4 E
AppName db "Crackme 5 Patch",0
) X3 z. T& |9 l- [5 |2 ~4 VDone db "File patched succesfully !",03 e: f4 u- g( ^& W0 ]4 L5 V& d: ^
NoFile db "Can't find crackme5.exe !",0
' ^7 {$ P. }- e; i* A+ j* ^& ?ReFile db "Wrong version of crackme5.exe !",06 e' m. E$ [: f0 u( f j; P
WrFile db "Error writing to crackme5.exe !",0
3 e( n& B+ z' ]' D6 E( V9 g% bRBuffer db 75h, 15h
* M t$ q* J, i; O, }WBuffer db 90h,90h( e4 v O* z+ b' ~8 [
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL> * i! k3 z8 i5 p
, h7 m: U) F) `: D6 x) L' [
.data?, r# F6 I% W9 f% R' m! m: G3 t+ X
, W" ^, @! k& [+ M" h' h5 k
hInstance HINSTANCE ?9 f& y2 _% a; q' y
CommandLine LPSTR ?
7 ?) t9 z3 v4 ]7 D) c' Yhwndname HWND ?
- O2 x% P+ _# f nhFile HANDLE ?9 C; J% k! j1 Z7 I
Numb dd ?7 M; S& p# K. M* A K. P
Buffer db 2 dup(?) ! y$ P) I1 A2 D: l2 r6 }
% e" C7 j! j) [4 |7 o. e
/ {# \3 w0 C6 B/ g5 h5 Q6 L2 ^+ Z.const
7 s- a; Q% [( S' `# c, Z . O+ l/ m7 X4 F" K* E( I/ ?
.code
% n3 h7 _: I3 Q' E Cstart:) z; `( ?8 k9 i; h
$ \- d( V8 b6 b5 ?* d" b
invoke GetModuleHandleA, NULL4 s. a4 c/ ^; I F Q
mov hInstance,eax 9 o; ]$ H( [( u- }* I
* Z# ]- [: u+ o% z
invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL 3 |6 S* E, o/ O& Z5 S! O2 H
8 b6 s0 @% r+ h, f+ J
.IF eax!=INVALID_HANDLE_VALUE% v4 G1 E1 J; E+ l5 p
0 }: h0 z4 Z( J$ g2 d5 W
mov hFile, eax ; 存储文件句柄$ J3 v+ }! E" _
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; 读取要修改的2个字节* S0 i% m" F C4 @
mov ax, word ptr [Buffer]
5 k* n* [4 m4 s8 {3 z4 b- ]) [.IF ax == word ptr [RBuffer] ; 如果判断正确 (75h,15h) 就覆盖他们 :-)0 F2 O3 m% H+ m- U9 [8 s, t% u* F
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ;写入新的代码(90h 90h)
% c( X8 B8 g' d% p! [2 Q.IF Numb == 2 ; 如果返回值为 2, 弹出成功信息
' v, R, _: I" j% [6 hpush MB_OK 3 R% \2 z- p# K' k+ |0 y' ~! h7 ^3 ~7 K
push OFFSET AppName
+ Y1 q" M+ Z6 x+ P; z5 f' spush OFFSET Done ; 弹出信息地址入栈
: x) u3 x6 G; o" M4 I.ELSE ;如果返回值不是2,那么弹出错误信息
" F/ }6 y$ i% Q1 D4 ?9 Bpush MB_OK OR MB_ICONINFORMATION" ]) Y! b: d% @, S
push OFFSET AppName
! h# R1 c. @5 ^8 ]# Fpush OFFSET WrFile) v" p! `2 w# K) h/ @% ]! r
.ENDIF ! m! W& J+ f2 s
.ELSE ; 如果读取的2个字节不正确,弹出文件选择错误信息' z: Z0 H1 p( t o
push MB_OK OR MB_ICONINFORMATION! U$ l2 o* e8 L" U
push OFFSET AppName1 Z/ O* c; T b4 s6 d3 y. R- ~
push OFFSET ReFile $ H! ?% |6 v6 r+ i4 D v& }
.ENDIF
7 z! q& o/ R3 |# t. q2 U8 ^- ^3 Q8 j; P
.ELSE ; 如果未获得文件句柄,弹出文件不存在信息
6 A- j: o# Q3 w* \7 u7 Upush MB_OK OR MB_ICONINFORMATION' m/ s8 E+ Q. e7 a
push OFFSET AppName8 j+ `7 k; B2 x9 r
push OFFSET NoFile 2 c2 r7 S& e# c( ~% V/ e
.ENDIF
$ `# g! i& I! C- Z G+ q
5 i- E8 B& u1 \1 X p# ?, t1 zpush NULL8 m, d9 q/ u: t0 K j f2 a; `
Call MessageBox
6 }* S) [& g% |invoke CloseHandle, hFile ; 关闭文件
/ F. l3 A7 W1 S: ^7 Rinvoke ExitProcess,eax ; 退出. c$ y5 [; X! _/ Y; x4 D
@ {6 n. w, p% |
end start% l. F; c B! d. ]
- N6 a& g4 r! ~% M7 c 如果你看懂了上面的代码,就可以制作自己的文件补丁。当然也可以编写的更人性化一些,比如添加上选择文件路径的对话框,但那就是另外一个题目了。 % T8 I0 B" M# l! b- h
0 ?" M7 p& b: H `9 O3 q
var currentpos,timer;
- q2 Y+ K$ Z- n6 ~: P( s7 c' d5 R" ~0 L, V5 Q, y7 ~+ A, Z# r- d% N
function initialize()
* c" Z; }: K5 ~9 |{
6 |3 K, F( |! a% j- u1 h: _timer=setInterval("scrollwindow()",10);
$ {+ A1 J8 F' e# u" \4 h' L, T}+ ~; j+ P8 {' n' k
function sc(){6 ~- H2 k) _$ Q7 ? [3 K6 u
clearInterval(timer);( C/ s# ]2 Q4 R, v" B
}# q+ G# l: D0 ]0 ~
function scrollwindow()! n4 \. z) K8 W7 [ t. v0 A& C! @8 L
{
; v" ^- L: ~6 ]9 p* g& z A$ g3 scurrentpos=document.body.scrollTop;* x4 N+ a. V+ O+ g4 B
window.scroll(0,++currentpos);
h1 w- h! `* [0 {4 R: F% |# dif (currentpos != document.body.scrollTop)
. {" w0 o! i! T6 E. d, Zsc(); _) h$ n* h2 R( {/ ]
}
$ U5 z" e0 t! D$ C( Y" d4 b+ zdocument.onmousedown=sc8 p' r5 S# e. l$ D3 }: e
document.ondblclick=initialize5 v, ]& g2 e3 M- q" r9 z8 f
X" r; \+ J- Q/ b6 H
/ `) {0 C) A( @( o |