-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathshellcode_windows.go
More file actions
208 lines (188 loc) · 6.87 KB
/
shellcode_windows.go
File metadata and controls
208 lines (188 loc) · 6.87 KB
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// Code generated by build script; DO NOT EDIT
// This file contains pre-compiled shellcode for remote thread injection
//go:build windows
package jambo
// remoteThreadShellcodeX64 is the x64 assembly code that runs in the remote JVM process
// Assembly source (NASM syntax):
//
// ; Input: RCX = pointer to callData structure
// ; Returns: RAX = result code
//
// push rbp
// mov rbp, rsp
// sub rsp, 0x60 ; Shadow space + locals
// mov [rbp-0x08], rcx ; Save callData pointer
//
// ; Get jvm.dll handle
// mov rcx, [rbp-0x08] ; callData
// lea rdx, [rcx+0x10] ; callData->strJvm
// mov rax, [rcx] ; callData->GetModuleHandleA
// call rax
// test rax, rax
// jz error_no_jvm ; Jump if NULL
// mov [rbp-0x10], rax ; Save jvm.dll handle
//
// ; Get JVM_EnqueueOperation address
// mov rcx, [rbp-0x10] ; jvm.dll handle
// mov rdx, [rbp-0x08] ; callData
// lea rdx, [rdx+0x30] ; callData->strEnqueue + 1
// mov rax, [rbp-0x08]
// mov rax, [rax+0x08] ; callData->GetProcAddress
// call rax
// test rax, rax
// jnz got_function ; Jump if not NULL
//
// ; Try alternative name: _JVM_EnqueueOperation@20
// mov rcx, [rbp-0x10] ; jvm.dll handle
// mov rdx, [rbp-0x08] ; callData
// lea rdx, [rdx+0x2F] ; callData->strEnqueue
// mov rax, [rbp-0x08]
// mov rax, [rax+0x08] ; callData->GetProcAddress
// call rax
// test rax, rax
// jz error_no_function ; Jump if NULL
//
// got_function:
// mov [rbp-0x18], rax ; Save JVM_EnqueueOperation address
//
// ; Call JVM_EnqueueOperation(args[0], args[1], args[2], args[3], pipeName)
// mov r9, [rbp-0x08] ; callData
// lea r9, [r9+0x130] ; callData->pipeName
// mov rax, [rbp-0x08]
// lea r8, [rax+0x930] ; callData->args[3]
// lea rdx, [rax+0x530] ; callData->args[2]
// lea rcx, [rax+0x130] ; callData->args[0]
// ; Note: args[1] is at callData + 0x330, but x64 calling convention
// ; uses registers for first 4 args, so we need to adjust
// mov rax, [rbp-0x08]
// lea rax, [rax+0x330] ; callData->args[1]
// mov [rsp+0x28], r9 ; 5th arg on stack
// mov r9, rax ; 4th arg in R9
// mov rax, [rbp-0x18] ; JVM_EnqueueOperation address
// call rax
// jmp done
//
// error_no_jvm:
// mov rax, 1001
// jmp done
//
// error_no_function:
// mov rax, 1002
//
// done:
// add rsp, 0x60
// pop rbp
// ret
var remoteThreadShellcodeX64 = []byte{
// Function prologue
0x55, // push rbp
0x48, 0x89, 0xE5, // mov rbp, rsp
0x48, 0x83, 0xEC, 0x60, // sub rsp, 0x60
0x48, 0x89, 0x4D, 0xF8, // mov [rbp-0x08], rcx
// Get GetModuleHandleA
0x48, 0x8B, 0x4D, 0xF8, // mov rcx, [rbp-0x08]
0x48, 0x8D, 0x51, 0x10, // lea rdx, [rcx+0x10]
0x48, 0x8B, 0x01, // mov rax, [rcx]
0xFF, 0xD0, // call rax
0x48, 0x85, 0xC0, // test rax, rax
0x74, 0x57, // jz error_no_jvm (offset +0x57)
0x48, 0x89, 0x45, 0xF0, // mov [rbp-0x10], rax
// Get JVM_EnqueueOperation (try without underscore first)
0x48, 0x8B, 0x4D, 0xF0, // mov rcx, [rbp-0x10]
0x48, 0x8B, 0x55, 0xF8, // mov rdx, [rbp-0x08]
0x48, 0x8D, 0x52, 0x31, // lea rdx, [rdx+0x31] (skip underscore)
0x48, 0x8B, 0x45, 0xF8, // mov rax, [rbp-0x08]
0x48, 0x8B, 0x40, 0x08, // mov rax, [rax+0x08]
0xFF, 0xD0, // call rax
0x48, 0x85, 0xC0, // test rax, rax
0x75, 0x1F, // jnz got_function (offset +0x1F)
// Try alternative name with underscore
0x48, 0x8B, 0x4D, 0xF0, // mov rcx, [rbp-0x10]
0x48, 0x8B, 0x55, 0xF8, // mov rdx, [rbp-0x08]
0x48, 0x8D, 0x52, 0x30, // lea rdx, [rdx+0x30]
0x48, 0x8B, 0x45, 0xF8, // mov rax, [rbp-0x08]
0x48, 0x8B, 0x40, 0x08, // mov rax, [rax+0x08]
0xFF, 0xD0, // call rax
0x48, 0x85, 0xC0, // test rax, rax
0x74, 0x33, // jz error_no_function (offset +0x33)
// got_function:
0x48, 0x89, 0x45, 0xE8, // mov [rbp-0x18], rax
// Prepare arguments for JVM_EnqueueOperation
// x64 calling convention: RCX, RDX, R8, R9, then stack
0x48, 0x8B, 0x4D, 0xF8, // mov rcx, [rbp-0x08]
0x48, 0x8D, 0x89, 0x50, 0x01, 0x00, 0x00, // lea rcx, [rcx+0x150] ; args[0]
0x48, 0x8B, 0x55, 0xF8, // mov rdx, [rbp-0x08]
0x48, 0x8D, 0x92, 0x50, 0x05, 0x00, 0x00, // lea rdx, [rdx+0x550] ; args[1]
0x4C, 0x8B, 0x45, 0xF8, // mov r8, [rbp-0x08]
0x4D, 0x8D, 0x80, 0x50, 0x09, 0x00, 0x00, // lea r8, [r8+0x950] ; args[2]
0x4C, 0x8B, 0x4D, 0xF8, // mov r9, [rbp-0x08]
0x4D, 0x8D, 0x89, 0x50, 0x0D, 0x00, 0x00, // lea r9, [r9+0xD50] ; args[3]
0x48, 0x8B, 0x45, 0xF8, // mov rax, [rbp-0x08]
0x48, 0x8D, 0x80, 0x50, 0x00, 0x00, 0x00, // lea rax, [rax+0x50] ; pipeName
0x48, 0x89, 0x44, 0x24, 0x20, // mov [rsp+0x20], rax ; 5th arg
0x48, 0x8B, 0x45, 0xE8, // mov rax, [rbp-0x18]
0xFF, 0xD0, // call rax
0xEB, 0x0A, // jmp done (offset +0x0A)
// error_no_jvm:
0x48, 0xC7, 0xC0, 0xE9, 0x03, 0x00, 0x00, // mov rax, 1001
0xEB, 0x07, // jmp done (offset +0x07)
// error_no_function:
0x48, 0xC7, 0xC0, 0xEA, 0x03, 0x00, 0x00, // mov rax, 1002
// done:
0x48, 0x83, 0xC4, 0x60, // add rsp, 0x60
0x5D, // pop rbp
0xC3, // ret
}
// remoteThreadShellcodeX86 is the x86 assembly code (32-bit)
// For 32-bit compatibility
var remoteThreadShellcodeX86 = []byte{
// Function prologue
0x55, // push ebp
0x89, 0xE5, // mov ebp, esp
0x83, 0xEC, 0x20, // sub esp, 0x20
// Get callData from stack (first parameter at [ebp+8])
0x8B, 0x45, 0x08, // mov eax, [ebp+8]
0x89, 0x45, 0xFC, // mov [ebp-4], eax
// Call GetModuleHandleA("jvm")
0x8B, 0x45, 0xFC, // mov eax, [ebp-4]
0x8D, 0x48, 0x10, // lea ecx, [eax+0x10]
0x51, // push ecx
0x8B, 0x00, // mov eax, [eax]
0xFF, 0xD0, // call eax
0x85, 0xC0, // test eax, eax
0x74, 0x35, // jz error_no_jvm
0x89, 0x45, 0xF8, // mov [ebp-8], eax
// Call GetProcAddress
0x8B, 0x45, 0xFC, // mov eax, [ebp-4]
0x8D, 0x48, 0x31, // lea ecx, [eax+0x31]
0x51, // push ecx
0x50, // push eax (jvm handle)
0x8B, 0x45, 0xFC, // mov eax, [ebp-4]
0x8B, 0x40, 0x04, // mov eax, [eax+4]
0xFF, 0xD0, // call eax
0x85, 0xC0, // test eax, eax
0x74, 0x23, // jz error_no_function
// Call JVM_EnqueueOperation
0x8B, 0x4D, 0xFC, // mov ecx, [ebp-4]
0x8D, 0x51, 0x50, // lea edx, [ecx+0x50] ; pipeName
0x52, // push edx
0x8D, 0x91, 0x50, 0x0D, 0x00, 0x00, // lea edx, [ecx+0xD50] ; args[3]
0x52, // push edx
0x8D, 0x91, 0x50, 0x09, 0x00, 0x00, // lea edx, [ecx+0x950] ; args[2]
0x52, // push edx
0x8D, 0x91, 0x50, 0x05, 0x00, 0x00, // lea edx, [ecx+0x550] ; args[1]
0x52, // push edx
0x8D, 0x91, 0x50, 0x01, 0x00, 0x00, // lea edx, [ecx+0x150] ; args[0]
0x52, // push edx
0xFF, 0xD0, // call eax
0xEB, 0x05, // jmp done
// error_no_jvm:
0xB8, 0xE9, 0x03, 0x00, 0x00, // mov eax, 1001
0xEB, 0x05, // jmp done
// error_no_function:
0xB8, 0xEA, 0x03, 0x00, 0x00, // mov eax, 1002
// done:
0x89, 0xEC, // mov esp, ebp
0x5D, // pop ebp
0xC2, 0x04, 0x00, // ret 4
}