• 标 题:(译) 内存补丁的制作实例-修改WDASM
  • 作 者:virtualspace
  • 时 间:2003年10月30日 08:57
  • 链 接:http://bbs.pediy.com

(译) 内存补丁的制作实例-修改WDASM   

VB32Dasm - by Lord Rhesus - Assembler-Source
Posted by: AntiCrack on Apr 07, 2002 - 03:27 PM

这个演示程序,试图告诉你应该如何编写一个调用程序,使用它来解决在另一个可执行程序中存在的问题。举个例子,怎样在WDASM 8.93中使用一个补丁,使它可以允许参照VB字符串(以前不行)。对于这个功能,补丁调用程序好过直接修改WDASM 8.93。如果那样,当WDASM调用非VB编译的程序是会有问题。

调用补丁子程序中,只需要简单定义新旧字节,去修补目标程序中的数据段内容,格式如下:

调用指令 函数名称    内存地址,      新内容指针,  旧内容指针, 修改的字节数
invoke   PatchBytes, address in mem, new bytes,  old bytes,  number of bytes

程序中重复地如此调用去修改一系列字节

这个补丁程序已经在使用了如下的压缩/保护外壳的程序中测试过:
UPX 1.01 by Markus Oberhumer & Laszlo Molnar (我推荐的压缩程序)
Petite 2.2 by Ian Luck (不错,但压缩速度慢)
PECompact 1.40b6 by Jeremy Collake (压缩比不错) 

在asprotect 1.00的演示版本中出现问题,因为它显示一个提示框,提示你的程序被asprotect 1.00演示版保护。为了允许被asprotect演示版保护的程序可以使用我们的补丁,需要放一个信息框在初始化内存补丁的子程序前(如后面的演示中被注释的部分),在程序被装入内存后,让用户按OK键。

注意,可能你还要在使用了注册版asprotect如此处理,因为它使用了反跟踪脚本。不过我没有测试过那些版本。

所有荣耀应该归于r!sc,许多好的想法来自于他的补丁程序。任何抱怨和建议应该给予我。我还在学习 Win32asm,因此我的汇编技术并不很好。

Lord Rhesus
email: lordrhesus@yahoo.co.uk 

;以下是作者提供的汇编源代码
.386
.model flat, stdcall
option casemap:none
include masm32includewindows.inc
include masm32includekernel32.inc
include masm32includeuser32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.lib

PatchBytes  proto :DWORD, :DWORD, :DWORD, :DWORD  ;补丁子程序原型定义

;数据段
.data
;MsgWaitTitle      db "Waiting",0                   ;这仅仅为了演示
;MsgWaitText       db "Click OK when program loaded",0 ;为了避免 asprotect 演示版产生的问题。如果你的程序有此问题,请允许此行被编译(去掉前面的‘;’号)

Msgerror          db "Error!",0
Msgcperror        db "File W32dsm89.exe not found!", 0dh, 0ah, "(确定调用程序与WDASM在同一目录)",0
Msgwperror        db "Error Writing to Memory!",0dh, 0ah, "(如果WDASM已被调用,则关闭它!)",0
Msgwrongver       db "Wrong Application or WDASM Changed!",0dh, 0ah, "(关闭被打开的应用程序!)",0
ProgName          db "W32dsm89.exe",0
OldBytes_1        db 40, 246, 0              ;28,F6 (以ASCII码显示的字节)
NewBytes_1        db 152, 244,0              ;98,F4
OldBytes_2        db "W32",0                 ;在提示条上待修改的字符
NewBytes_2        db "VB ",0                 ;在提示条上改后的字符
processInfo PROCESS_INFORMATION <>
startInfo   STARTUPINFO <>
counter           DWORD ?                  ;在补丁子程序PatchBytes中使用的计数器
readres           LPSTR ?                    ;读出的被保存的结果

代码段
.code
start:

invoke CreateProcessA, addr ProgName, NULL, NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, addr startInfo, addr processInfo  ;创建W32dsm89.exe进程
        test eax, eax
        jz  MsgFileNotFound
        invoke ResumeThread, dword ptr [processInfo + 4]

   ;invoke MessageBox, NULL,addr MsgWaitText, addr MsgWaitTitle, MB_OK 
;避免 asprotect 演示版中出现的问题,如果你被补丁的程序使用了asprotect 演示版保护,请允许这一行程序被编译(去掉前面的‘;’号)

  invoke PatchBytes, 0041756ch, addr NewBytes_1, addr OldBytes_1, 2h
     invoke PatchBytes, 004bc4fDh, addr NewBytes_2, addr OldBytes_2, 3h
        
ExitLoader:
        invoke CloseHandle, dword ptr [processInfo]
        invoke CloseHandle, dword ptr [processInfo + 4]
        invoke ExitProcess, NULL
;
;########### 错误信息提示 开始#######--ERROR-MESSAGES-START--########
MsgWrongVersion:
        lea eax, Msgwrongver
        jmp DisplayMsg
MsgFileNotFound:
        lea eax, Msgcperror
        jmp DisplayMsg
MsgMemWriteError:
        lea eax, Msgwperror
DisplayMsg:
        invoke MessageBoxA, NULL, eax, addr Msgerror, NULL
        jmp ExitLoader
;######## 错误信息提示 开始####--ERROR-MESSAGES-CLOSE--##

;#### 补丁子程序开始 #####--PATCHBYTES-PROCEDURE-START--######
PatchBytes proc MemLoc:DWORD, NewBytes:DWORD, OldBytes:DWORD, NoBytes:DWORD
GetPatchBytes:
        xor ebx, ebx
        mov ebx, dword ptr [NoBytes]  ; 在ebx中放入待修改的字节数
        mov edi, dword ptr [OldBytes] ;待修改的字节
        mov counter, 0h               ; 重置计数器
CheckBytesPresent:
        inc counter
        cmp counter, 8000            ;是否达到了最大循环等待次数(可以增加,为了等待被调用的程序完全被解码)
        jz MsgWrongVersion
        
        invoke ReadProcessMemory, dword ptr [processInfo], dword ptr [MemLoc], addr readres, ebx, NULL   ;读内存进程
        pusha
        lea esi, readres
        mov ecx, ebx                 ;ebx中保存着待比较的字节数
        repe cmpsb         ;重复比较,检查内存是否出现应该被修改的相关字节
        popa
        jnz CheckBytesPresent        ;如果不相等就跳转  并且再次检查
        mov eax, dword ptr [NewBytes]
        invoke WriteProcessMemory, dword ptr [processInfo], dword ptr [MemLoc], eax, ebx, NULL    ;调用写进程,修改相应的字节
        test eax, eax
        jz MsgMemWriteError ;不成功则提示错误信息
        ret
PatchBytes endp
;### # 补丁子程序结束 ###--PATCHBYTES-PROCEDURE-CLOSE--#####

end start
;全部程序结束