1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
; call gate transition
GLOBAL cg_entry
EXTERN cg_decrypt
EXTERN cg_find
struc callgate
sav0: resd 1
sav4: resd 1
ra_sav: resd 1
ar_beg: resd 1
ar_len: resd 1
keyptr: resd 1
endstruc
; the central call gate jump-point
;
; we are called by an encrypted function if we land here. we have to restore
; its encrypted state, then decrypt it. afterwards we optionally setup a trap
; return address that will return into a re-encryption function.
;
; 0x0000: 0x50 push %eax == gate address
; 0x0001: 0x60 pusha
; 0x0002: 0x9c pushf
; 0x0003: 0xe8 0x00 0x00 0x00 0x00 call cg_entry
cg_entry:
; int 0x03
push eax
pusha
pushf
call cg_foo
ret
nop
nop
cg_foo:
pop esi
sub esi, 8
push esi
call cg_find ; in: esi, out: eax = struct *
add esp, dword 4
; restore bytes taken by the gate
mov edx, [eax + sav0]
mov [esi], edx
mov edx, [eax + sav4]
mov [esi + 4], edx
; save real return address, overwrite with encryption gate addr, yay!
mov edx, [esp + 0x28]
mov [eax + ra_sav], edx
mov [esp + 0x28], dword cg_encryptgate
; decrypt the whole encrypted function
push eax
call cg_decrypt
add esp, dword 4
mov [esp + 0x24], esi ; overwrite dummy eax value
popf
popa
ret
cg_encryptgate:
ret
|