📄 29a-7.019
字号:
push eax
push PAGE_EXECUTE_READWRITE
lea eax,[esi+00Ch]
push [eax]
push [esi]
call VirtualProtect ;we will change protection for a moment
;so we will be able to write there
test eax,eax
jz free_mem
mov byte ptr [edi],0E9h ;to write relative jump
mov eax,offset new_sleep
sub eax,edi
sub eax,5
inc edi
stosd ;this is relative address for jump
push offset old_protect
lea eax,[esi+014h]
push [eax]
lea eax,[esi+00Ch]
push [eax]
push [esi]
call VirtualProtect ;return back the protection of page
free_mem:
push MEM_RELEASE
push 0
push esi
call VirtualFree ;free memory
do_sleep:
push 5000
call Sleep
push 0
call ExitProcess
new_sleep:
ret 004h
end start
Result of the second call Sleep is this:
004010A4: 6888130000 push 000001388h
004010A9: E80A000000 call Sleep
Sleep: ;toto je jump na adresu v IAT
004010B8: FF2514204000 jmp dword ptr [000402014h]
tabulka:
00402014: 79 67 E8 77 6C 7D E8 77
Kernel32.Sleep:
77E86779: E937A95788 jmp 0004010B5h
new_sleep:
004010B5: C20400 ret 004h
=====[ 3.2.3 Original function saving ]=========================================
Mostly we need more than a function hook. For example in case when we
don't want to replace the given function but only to check its result, or in
case when we want to replace the function only sometimes e.g. when it is called
with specific arguments. Good example of this is already mentioned files hiding
done by replacing FindXXXFile functions. So if we want to hide specific files
and don't want to be noticeable we have to leave original function for all
other files without changing the functions behavior. This is simple when using
method of rewriting IAT. For calling original function we can get its original
address with GetProcAddress and then call it directly. But the problem occurs
when using rewriting entry point method. By rewriting those 5 bytes at the
functions entry point we lost original function irrecoverably. So we need to
save first instructions. We can use following technic.
We know we will rewrite only first 5 bytes but don't know how many
instructions there are or how long they are. We have to reserve enough memory
for first instructions. 16 bytes could be enought because there are usually not
long instructions at the begin of function. Probably we can use less then 16.
Whole reserverd memory will be filled with 0x90 (0x90 = nop) in case there
are shorter instructions. Next 5 bytes will be relative jump which will be
filled later.
old_hook: db 090h,090h,090h,090h,090h,090h,090h,090h
db 090h,090h,090h,090h,090h,090h,090h,090h
db 0E9h,000h,000h,000h,000h
Now we are ready to copy first instructions. It is a long stuff to get
instruction length, this is why we will work with the complete engine. This
was made by Z0MBiE. Input argument is instruction address for which we want to
get length. Output is commonly in eax.
; LDE32, Length-Disassembler Engine, 32-bit, (x) 1999-2000 Z0MBiE
; special edition for REVERT tool
; version 1.05
C_MEM1 equ 0001h ; |
C_MEM2 equ 0002h ; |may be used simultaneously
C_MEM4 equ 0004h ; |
C_DATA1 equ 0100h ; |
C_DATA2 equ 0200h ; |may be used simultaneously
C_DATA4 equ 0400h ; |
C_67 equ 0010h ; used with C_PREFIX
C_MEM67 equ 0020h ; C_67 ? C_MEM2 : C_MEM4
C_66 equ 1000h ; used with C_PREFIX
C_DATA66 equ 2000h ; C_66 ? C_DATA2 : C_DATA4
C_PREFIX equ 0008h ; prefix. take opcode again
C_MODRM equ 4000h ; MODxxxR/M
C_DATAW0 equ 8000h ; opc&1 ? C_DATA66 : C_DATA1
p386
model flat
locals @@
.code
public disasm_main
public _disasm_main
public @disasm_main
public DISASM_MAIN
disasm_main:
_disasm_main:
@disasm_main:
DISASM_MAIN:
; returns opcode length in EAX or -1 if error
; input: pointer to opcode
; __fastcall EAX
; __cdecl [ESP+4]
;this is my first change here, it's the label only for calling this function
get_instr_len:
mov ecx, [esp+4] ; ECX = opcode ptr
xor edx, edx ; flags
xor eax, eax
@@prefix: and dl, not C_PREFIX
mov al, [ecx]
inc ecx
or edx, table_1[eax*4]
test dl, C_PREFIX
jnz @@prefix
cmp al, 0F6h
je @@test
cmp al, 0F7h
je @@test
cmp al, 0CDh
je @@int
cmp al, 0Fh
je @@0F
@@cont:
test dh, C_DATAW0 shr 8
jnz @@dataw0
@@dataw0done:
test dh, C_MODRM shr 8
jnz @@modrm
@@exitmodrm:
test dl, C_MEM67
jnz @@mem67
@@mem67done:
test dh, C_DATA66 shr 8
jnz @@data66
@@data66done:
mov eax, ecx
sub eax, [esp+4]
and edx,C_MEM1+C_MEM2+C_MEM4+C_DATA1+C_DATA2+C_DATA4
add al, dl
add al, dh
;my second change heer, there was retn only in original version
@@exit: ret 00004h
@@test: or dh, C_MODRM shr 8
test byte ptr [ecx], 00111000b ; F6/F7 -- test
jnz @@cont
or dh, C_DATAW0 shr 8
jmp @@cont
@@int: or dh, C_DATA1 shr 8
cmp byte ptr [ecx], 20h
jne @@cont
or dh, C_DATA4 shr 8
jmp @@cont
@@0F: mov al, [ecx]
inc ecx
or edx, table_0F[eax*4]
cmp edx, -1
jne @@cont
@@error: mov eax, edx
jmp @@exit
@@dataw0: xor dh, C_DATA66 shr 8
test al, 00000001b
jnz @@dataw0done
xor dh, (C_DATA66+C_DATA1) shr 8
jmp @@dataw0done
@@mem67: xor dl, C_MEM2
test dl, C_67
jnz @@mem67done
xor dl, C_MEM4+C_MEM2
jmp @@mem67done
@@data66: xor dh, C_DATA2 shr 8
test dh, C_66 shr 8
jnz @@data66done
xor dh, (C_DATA4+C_DATA2) shr 8
jmp @@data66done
@@modrm: mov al, [ecx]
inc ecx
mov ah, al ; ah=mod, al=rm
and ax, 0C007h
cmp ah, 0C0h
je @@exitmodrm
test dl, C_67
jnz @@modrm16
@@modrm32: cmp al, 04h
jne @@a
mov al, [ecx] ; sib
inc ecx
and al, 07h
@@a: cmp ah, 40h
je @@mem1
cmp ah, 80h
je @@mem4
cmp ax, 0005h
jne @@exitmodrm
@@mem4: or dl, C_MEM4
jmp @@exitmodrm
@@mem1: or dl, C_MEM1
jmp @@exitmodrm
@@modrm16: cmp ax, 0006h
je @@mem2
cmp ah, 40h
je @@mem1
cmp ah, 80h
jne @@exitmodrm
@@mem2: or dl, C_MEM2
jmp @@exitmodrm
endp
.data
;0F -- analyzed in code, no flags (i.e.flags must be 0)
;F6,F7 -- --//-- (ttt=000 -- 3 bytes, otherwise 2 bytes)
;CD -- --//-- (6 bytes if CD 20, 2 bytes otherwise)
table_1 label dword ; normal instructions
dd C_MODRM ; 00
dd C_MODRM ; 01
dd C_MODRM ; 02
dd C_MODRM ; 03
dd C_DATAW0 ; 04
dd C_DATAW0 ; 05
dd 0 ; 06
dd 0 ; 07
dd C_MODRM ; 08
dd C_MODRM ; 09
dd C_MODRM ; 0A
dd C_MODRM ; 0B
dd C_DATAW0 ; 0C
dd C_DATAW0 ; 0D
dd 0 ; 0E
dd 0 ; 0F
dd C_MODRM ; 10
dd C_MODRM ; 11
dd C_MODRM ; 12
dd C_MODRM ; 13
dd C_DATAW0 ; 14
dd C_DATAW0 ; 15
dd 0 ; 16
dd 0 ; 17
dd C_MODRM ; 18
dd C_MODRM ; 19
dd C_MODRM ; 1A
dd C_MODRM ; 1B
dd C_DATAW0 ; 1C
dd C_DATAW0 ; 1D
dd 0 ; 1E
dd 0 ; 1F
dd C_MODRM ; 20
dd C_MODRM ; 21
dd C_MODRM ; 22
dd C_MODRM ; 23
dd C_DATAW0 ; 24
dd C_DATAW0 ; 25
dd C_PREFIX ; 26
dd 0 ; 27
dd C_MODRM ; 28
dd C_MODRM ; 29
dd C_MODRM ; 2A
dd C_MODRM ; 2B
dd C_DATAW0 ; 2C
dd C_DATAW0 ; 2D
dd C_PREFIX ; 2E
dd 0 ; 2F
dd C_MODRM ; 30
dd C_MODRM ; 31
dd C_MODRM ; 32
dd C_MODRM ; 33
dd C_DATAW0 ; 34
dd C_DATAW0 ; 35
dd C_PREFIX ; 36
dd 0 ; 37
dd C_MODRM ; 38
dd C_MODRM ; 39
dd C_MODRM ; 3A
dd C_MODRM ; 3B
dd C_DATAW0 ; 3C
dd C_DATAW0 ; 3D
dd C_PREFIX ; 3E
dd 0 ; 3F
dd 0 ; 40
dd 0 ; 41
dd 0 ; 42
dd 0 ; 43
dd 0 ; 44
dd 0 ; 45
dd 0 ; 46
dd 0 ; 47
dd 0 ; 48
dd 0 ; 49
dd 0 ; 4A
dd 0 ; 4B
dd 0 ; 4C
dd 0 ; 4D
dd 0 ; 4E
dd 0 ; 4F
dd 0 ; 50
dd 0 ; 51
dd 0 ; 52
dd 0 ; 53
dd 0 ; 54
dd 0 ; 55
dd 0 ; 56
dd 0 ; 57
dd 0 ; 58
dd 0 ; 59
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -