mirror of
https://github.com/rainerzufalldererste/windows_x64_shellcode_template
synced 2026-06-08 16:57:13 +00:00
Using AddressOfNameOrdinals when resolving the function name index to the corresponding address
This commit is contained in:
@@ -25,13 +25,13 @@ There are a lot of comments in the `shellcode_template` function to better expla
|
||||
IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pKernel32TableEntry->DllBase;
|
||||
|
||||
// In order to get the exported functions we need to go to the NT PE header.
|
||||
IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((uint8_t *)pDosHeader + pDosHeader->e_lfanew);
|
||||
IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((size_t)pDosHeader + pDosHeader->e_lfanew);
|
||||
|
||||
// From the NtHeader we can extract the virtual address of the export directory of this module.
|
||||
IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((uint8_t *)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((size_t)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
// The exports directory contains both a list of function _names_ of this module and the associated _addresses_ of the functions.
|
||||
const int32_t *pNameOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfNames);
|
||||
const int32_t *pNameOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfNames);
|
||||
|
||||
// We will use this struct to store strings.
|
||||
// We are using a struct to make sure strings don't end up in another section of the executable where we wouldn't be able to address them in a different process.
|
||||
@@ -46,16 +46,19 @@ There are a lot of comments in the `shellcode_template` function to better expla
|
||||
int32_t i = 0;
|
||||
|
||||
// We're just extracting the first 8 bytes of the strings and compare them to `GetProcA`. We'll find it eventually.
|
||||
while (*(uint64_t *)((char *)pDosHeader + pNameOffsets[i]) != x.text0)
|
||||
while (*(uint64_t *)((size_t)pDosHeader + pNameOffsets[i]) != x.text0)
|
||||
++i;
|
||||
|
||||
// We have found the index of `GetProcAddress`.
|
||||
|
||||
// Not let's get the function offsets in order to retrieve the location of `GetProcAddress` in memory.
|
||||
const int32_t *pFunctionOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfFunctions);
|
||||
// The entry at an index in `AddressOfNames` corresponds to an entry at the same index in `AddressOfNameOrdinals`, which resolves the index of a given name to it's corresponding entry in `AddressOfFunctions`. (DLLs can export unnamed functions, which will not be listed in `AddressOfNames`.)
|
||||
// Let's get the function name ordinal offsets and function offsets in order to retrieve the location of `GetProcAddress` in memory.
|
||||
const int16_t *pFunctionNameOrdinalOffsets = (const int16_t *)((size_t)pDosHeader + pExports->AddressOfNameOrdinals);
|
||||
const int32_t *pFunctionOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfFunctions);
|
||||
|
||||
// Now resolve the index in `pFunctionOffsets` from `pFunctionNameOrdinalOffsets` to get the address of the desired function in memory.
|
||||
typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);
|
||||
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((uint8_t *)pDosHeader + pFunctionOffsets[i]);
|
||||
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((size_t)pDosHeader + pFunctionOffsets[pFunctionNameOrdinalOffsets[i]]);
|
||||
|
||||
// Now that we've got `GetProcAddress`, let's use it to get `LoadLibraryA`.
|
||||
|
||||
@@ -89,25 +92,23 @@ There are many ways to retrieve the generated shellcode.
|
||||
The easiest way is probably to just step into `void shellcode_template()` in the Visual Studio Debugger and open the Disassembly View (Ctrl+Alt+D). Make sure to turn on displaying code bytes and turn off displaying source code and addresses to simplify the output.
|
||||
|
||||
```asm
|
||||
shellcode_template:
|
||||
48 89 5C 24 08 mov qword ptr [rsp+8],rbx
|
||||
57 push rdi
|
||||
48 83 EC 30 sub rsp,30h
|
||||
65 48 8B 04 25 60 00 00 00 mov rax,qword ptr gs:[0000000000000060h]
|
||||
49 B9 47 65 74 50 72 6F 63 41 mov r9,41636F7250746547h
|
||||
33 D2 xor edx,edx
|
||||
49 B8 47 65 74 50 72 6F 63 41 mov r8,41636F7250746547h
|
||||
48 8B 48 18 mov rcx,qword ptr [rax+18h]
|
||||
48 8B 41 20 mov rax,qword ptr [rcx+20h]
|
||||
48 8B 08 mov rcx,qword ptr [rax]
|
||||
48 8B 01 mov rax,qword ptr [rcx]
|
||||
48 8B 78 20 mov rdi,qword ptr [rax+20h]
|
||||
48 63 47 3C movsxd rax,dword ptr [rdi+3Ch]
|
||||
44 8B 84 38 88 00 00 00 mov r8d,dword ptr [rax+rdi+0000000000000088h]
|
||||
41 8B 44 38 20 mov eax,dword ptr [r8+rdi+20h]
|
||||
44 8B 8C 38 88 00 00 00 mov r9d,dword ptr [rax+rdi+0000000000000088h]
|
||||
41 8B 44 39 20 mov eax,dword ptr [r9+rdi+20h]
|
||||
48 03 C7 add rax,rdi
|
||||
4C 89 4C 24 20 mov qword ptr [rsp+20h],r9
|
||||
48 63 08 movsxd rcx,dword ptr [rax]
|
||||
4C 39 0C 39 cmp qword ptr [rcx+rdi],r9
|
||||
4C 39 04 39 cmp qword ptr [rcx+rdi],r8
|
||||
...
|
||||
```
|
||||
|
||||
@@ -118,24 +119,23 @@ Now you can just remove the labels and disassembly and you're left with the shel
|
||||
57
|
||||
48 83 EC 30
|
||||
65 48 8B 04 25 60 00 00 00
|
||||
49 B9 47 65 74 50 72 6F 63 41
|
||||
33 D2
|
||||
49 B8 47 65 74 50 72 6F 63 41
|
||||
48 8B 48 18
|
||||
48 8B 41 20
|
||||
48 8B 08
|
||||
48 8B 01
|
||||
48 8B 78 20
|
||||
48 63 47 3C
|
||||
44 8B 84 38 88 00 00 00
|
||||
41 8B 44 38 20
|
||||
44 8B 8C 38 88 00 00 00
|
||||
41 8B 44 39 20
|
||||
48 03 C7
|
||||
4C 89 4C 24 20
|
||||
48 63 08
|
||||
4C 39 0C 39
|
||||
4C 39 04 39
|
||||
...
|
||||
```
|
||||
|
||||
Alternatively you can just paste your code into an online compiler like [godbolt.org](https://godbolt.org/) and copy the generated MSVC assembly (ie. `x64 msvc v19.21`) into an online assembler like [https://defuse.ca/online-x86-assembler.htm](https://defuse.ca/online-x86-assembler.htm). Then just copy the generated shellcode.
|
||||
Alternatively you can just paste your code into an online compiler like [godbolt.org](https://godbolt.org/) and copy the generated MSVC assembly (that doesn't call any internal functions for i.e. buffer security cheacks or memcpy) (ie. `x64 msvc v19.latest` with `/O2 /GS-`) into an online assembler like [https://defuse.ca/online-x86-assembler.htm](https://defuse.ca/online-x86-assembler.htm). Then just copy the generated shellcode.
|
||||
|
||||
When using online compilers you will probably have to clean up the assembly a bit, like this:
|
||||
|
||||
@@ -148,28 +148,33 @@ $LN10:
|
||||
sub rsp, 48 ; 00000030H
|
||||
mov rax, QWORD PTR gs:96
|
||||
xor edx, edx
|
||||
mov r9, 4711732171926431047 ; 41636f7250746547H
|
||||
mov r8, 4711732171926431047 ; 41636f7250746547H
|
||||
mov rcx, QWORD PTR [rax+24]
|
||||
mov rax, QWORD PTR [rcx+32]
|
||||
mov rcx, QWORD PTR [rax]
|
||||
mov rax, QWORD PTR [rcx]
|
||||
mov rdi, QWORD PTR [rax+32]
|
||||
movsxd rax, DWORD PTR [rdi+60]
|
||||
mov r8d, DWORD PTR [rax+rdi+136]
|
||||
mov eax, DWORD PTR [r8+rdi+32]
|
||||
mov r9d, DWORD PTR [rax+rdi+136]
|
||||
mov eax, DWORD PTR [r9+rdi+32]
|
||||
add rax, rdi
|
||||
movsxd rcx, DWORD PTR [rax]
|
||||
cmp QWORD PTR [rcx+rdi], r9
|
||||
cmp QWORD PTR [rcx+rdi], r8
|
||||
je SHORT $LN3@shellcode_
|
||||
npad 2
|
||||
$LL2@shellcode_:
|
||||
movsxd rcx, DWORD PTR [rax+4]
|
||||
lea rax, QWORD PTR [rax+4]
|
||||
inc edx
|
||||
cmp QWORD PTR [rcx+rdi], r8
|
||||
jne SHORT $LL2@shellcode_
|
||||
$LN3@shellcode_:
|
||||
mov ecx, DWORD PTR [r9+rdi+36]
|
||||
mov rax, 8242266044863967052 ; 7262694c64616f4cH
|
||||
...
|
||||
```
|
||||
|
||||
can through a bit of find and replace be turned into this:
|
||||
can through a bit of find and replace be turned into this: (keep in mind, the defuse.ca assembler doesn't seem to like comments)
|
||||
|
||||
```asm
|
||||
shellcode_template:
|
||||
@@ -178,29 +183,37 @@ shellcode_template:
|
||||
sub rsp, 48
|
||||
mov rax, qword ptr gs:96
|
||||
xor edx, edx
|
||||
mov r9, 4711732171926431047
|
||||
mov r8, 4711732171926431047
|
||||
mov rcx, qword ptr [rax+24]
|
||||
mov rax, qword ptr [rcx+32]
|
||||
mov rcx, qword ptr [rax]
|
||||
mov rax, qword ptr [rcx]
|
||||
mov rdi, qword ptr [rax+32]
|
||||
movsxd rax, dword ptr [rdi+60]
|
||||
mov r8d, dword ptr [rax+rdi+136]
|
||||
mov eax, dword ptr [r8+rdi+32]
|
||||
movsxd rax, DWORD ptr [rdi+60]
|
||||
mov r9d, DWORD ptr [rax+rdi+136]
|
||||
mov eax, DWORD ptr [r9+rdi+32]
|
||||
add rax, rdi
|
||||
movsxd rcx, dword ptr [rax]
|
||||
cmp qword ptr [rcx+rdi], r9
|
||||
je short _function_found
|
||||
movsxd rcx, DWORD ptr [rax]
|
||||
cmp qword ptr [rcx+rdi], r8
|
||||
je SHORT _function_found
|
||||
|
||||
; `npad 2` can be turned into two `nop`s.
|
||||
|
||||
|
||||
nop
|
||||
nop
|
||||
|
||||
_check_next_function_name:
|
||||
movsxd rcx, dword ptr [rax+4]
|
||||
|
||||
_find_next_function:
|
||||
movsxd rcx, DWORD ptr [rax+4]
|
||||
lea rax, qword ptr [rax+4]
|
||||
inc edx
|
||||
cmp qword ptr [rcx+rdi], r8
|
||||
jne SHORT _find_next_function
|
||||
|
||||
|
||||
_function_found:
|
||||
mov ecx, DWORD ptr [r9+rdi+36]
|
||||
mov rax, 8242266044863967052
|
||||
...
|
||||
```
|
||||
|
||||
@@ -215,24 +228,25 @@ This is the example shellcode. It performs the following actions:
|
||||
+ calls `ExitProcess`.
|
||||
|
||||
```
|
||||
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60,
|
||||
0x00, 0x00, 0x00, 0x31, 0xD2, 0x49, 0xB9, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48,
|
||||
0x8B, 0x48, 0x18, 0x48, 0x8B, 0x41, 0x20, 0x48, 0x8B, 0x08, 0x48, 0x8B, 0x01, 0x48, 0x8B, 0x78,
|
||||
0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x84, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
|
||||
0x38, 0x20, 0x48, 0x01, 0xF8, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x0C, 0x39, 0x74, 0x12, 0x90, 0x90,
|
||||
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x0C, 0x39, 0x75, 0xF0,
|
||||
0x41, 0x8B, 0x4C, 0x38, 0x1C, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
|
||||
0x01, 0xF9, 0x48, 0x63, 0xD2, 0x48, 0x63, 0x1C, 0x91, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x01,
|
||||
0xFB, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0xF9, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72,
|
||||
0x79, 0x41, 0xFF, 0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7,
|
||||
0x44, 0x24, 0x28, 0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24,
|
||||
0x20, 0xFF, 0xD0, 0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44,
|
||||
0x24, 0x28, 0x6F, 0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20,
|
||||
0x48, 0x89, 0xC1, 0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C,
|
||||
0x8D, 0x44, 0x24, 0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9,
|
||||
0x20, 0x76, 0x69, 0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x31, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28,
|
||||
0x31, 0xC9, 0xFF, 0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7,
|
||||
0x44, 0x24, 0x28, 0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24,
|
||||
0x20, 0x48, 0x89, 0xF9, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C,
|
||||
0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC2, 0x00, 0x00
|
||||
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60,
|
||||
0x00, 0x00, 0x00, 0x33, 0xD2, 0x49, 0xB8, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48,
|
||||
0x8B, 0x48, 0x18, 0x48, 0x8B, 0x41, 0x20, 0x48, 0x8B, 0x08, 0x48, 0x8B, 0x01, 0x48, 0x8B, 0x78,
|
||||
0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x8C, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
|
||||
0x39, 0x20, 0x48, 0x03, 0xC7, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x04, 0x39, 0x74, 0x12, 0x66, 0x90,
|
||||
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x04, 0x39, 0x75, 0xF0,
|
||||
0x41, 0x8B, 0x4C, 0x39, 0x24, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
|
||||
0x03, 0xCF, 0x48, 0x63, 0xD2, 0x4C, 0x0F, 0xBF, 0x04, 0x51, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x41,
|
||||
0x8B, 0x4C, 0x39, 0x1C, 0x48, 0x03, 0xCF, 0x4A, 0x63, 0x1C, 0x81, 0x48, 0x8B, 0xCF, 0x48, 0x03,
|
||||
0xDF, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72, 0x79, 0x41, 0xFF,
|
||||
0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7, 0x44, 0x24, 0x28,
|
||||
0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0xD0,
|
||||
0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x6F,
|
||||
0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0xC8,
|
||||
0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C, 0x8D, 0x44, 0x24,
|
||||
0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9, 0x20, 0x76, 0x69,
|
||||
0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28, 0x33, 0xC9, 0xFF,
|
||||
0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7, 0x44, 0x24, 0x28,
|
||||
0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8B,
|
||||
0xCF, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48,
|
||||
0x83, 0xC4, 0x30, 0x5F, 0xC3
|
||||
```
|
||||
+11
-11
@@ -10,10 +10,10 @@ IF "%1"=="4" GOTO FOUR;
|
||||
ECHO INVALID PARAMETER (%1)
|
||||
|
||||
:MANUAL_CONFIG
|
||||
ECHO 1. Visual Studio 2017 Solution
|
||||
ECHO 2. Visual Studio 2015 Solution
|
||||
ECHO 3. Visual Studio 2013 Solution
|
||||
ECHO 4. gmake2 Makefile
|
||||
ECHO 1. Visual Studio 2019 Solution
|
||||
ECHO 2. Visual Studio 2017 Solution
|
||||
ECHO 3. Visual Studio 2015 Solution
|
||||
ECHO 4. Visual Studio 2013 Solution
|
||||
|
||||
CHOICE /N /C:1234 /M "[1-4]:"
|
||||
|
||||
@@ -24,24 +24,24 @@ IF ERRORLEVEL ==1 GOTO ONE
|
||||
GOTO END
|
||||
|
||||
:FOUR
|
||||
ECHO Creating gmake2 Makefile...
|
||||
premake\premake5.exe gmake2
|
||||
GOTO END
|
||||
|
||||
:THREE
|
||||
ECHO Creating VS2013 Project...
|
||||
premake\premake5.exe vs2013
|
||||
GOTO END
|
||||
|
||||
:TWO
|
||||
:THREE
|
||||
ECHO Creating VS2015 Project...
|
||||
premake\premake5.exe vs2015
|
||||
GOTO END
|
||||
|
||||
:ONE
|
||||
:TWO
|
||||
ECHO Creating VS2017 Project...
|
||||
premake\premake5.exe vs2017
|
||||
GOTO END
|
||||
|
||||
:ONE
|
||||
ECHO Creating VS2019 Project...
|
||||
premake\premake5.exe vs2019
|
||||
GOTO END
|
||||
|
||||
:END
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ project(ProjectName)
|
||||
--Settings
|
||||
kind "ConsoleApp"
|
||||
language "C"
|
||||
flags { "StaticRuntime", "FatalWarnings" }
|
||||
flags { "FatalWarnings" }
|
||||
staticruntime "On"
|
||||
|
||||
defines { "_CRT_SECURE_NO_WARNINGS" }
|
||||
|
||||
@@ -46,6 +47,7 @@ filter { "configurations:Debug*" }
|
||||
filter { "configurations:Release" }
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
flags { "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
omitframepointer "On"
|
||||
editandcontinue "Off"
|
||||
symbols "On"
|
||||
|
||||
@@ -4,7 +4,8 @@ project(ProjectName)
|
||||
--Settings
|
||||
kind "ConsoleApp"
|
||||
language "C"
|
||||
flags { "StaticRuntime", "FatalWarnings" }
|
||||
flags { "FatalWarnings" }
|
||||
staticruntime "On"
|
||||
|
||||
dependson { "child_process" }
|
||||
|
||||
@@ -48,6 +49,7 @@ filter { "configurations:Debug*" }
|
||||
filter { "configurations:Release" }
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
flags { "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
omitframepointer "On"
|
||||
editandcontinue "Off"
|
||||
symbols "On"
|
||||
|
||||
@@ -6,27 +6,28 @@
|
||||
#include <windows.h>
|
||||
#include <memoryapi.h>
|
||||
|
||||
const uint8_t shellcode[] = {
|
||||
const uint8_t shellcode[] = {
|
||||
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60,
|
||||
0x00, 0x00, 0x00, 0x31, 0xD2, 0x49, 0xB9, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48,
|
||||
0x00, 0x00, 0x00, 0x33, 0xD2, 0x49, 0xB8, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48,
|
||||
0x8B, 0x48, 0x18, 0x48, 0x8B, 0x41, 0x20, 0x48, 0x8B, 0x08, 0x48, 0x8B, 0x01, 0x48, 0x8B, 0x78,
|
||||
0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x84, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
|
||||
0x38, 0x20, 0x48, 0x01, 0xF8, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x0C, 0x39, 0x74, 0x12, 0x90, 0x90,
|
||||
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x0C, 0x39, 0x75, 0xF0,
|
||||
0x41, 0x8B, 0x4C, 0x38, 0x1C, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
|
||||
0x01, 0xF9, 0x48, 0x63, 0xD2, 0x48, 0x63, 0x1C, 0x91, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x01,
|
||||
0xFB, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0xF9, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72,
|
||||
0x79, 0x41, 0xFF, 0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7,
|
||||
0x44, 0x24, 0x28, 0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24,
|
||||
0x20, 0xFF, 0xD0, 0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44,
|
||||
0x24, 0x28, 0x6F, 0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20,
|
||||
0x48, 0x89, 0xC1, 0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C,
|
||||
0x8D, 0x44, 0x24, 0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9,
|
||||
0x20, 0x76, 0x69, 0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x31, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28,
|
||||
0x31, 0xC9, 0xFF, 0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7,
|
||||
0x44, 0x24, 0x28, 0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24,
|
||||
0x20, 0x48, 0x89, 0xF9, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C,
|
||||
0x24, 0x40, 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC2, 0x00, 0x00
|
||||
0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x8C, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,
|
||||
0x39, 0x20, 0x48, 0x03, 0xC7, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x04, 0x39, 0x74, 0x12, 0x66, 0x90,
|
||||
0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x04, 0x39, 0x75, 0xF0,
|
||||
0x41, 0x8B, 0x4C, 0x39, 0x24, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,
|
||||
0x03, 0xCF, 0x48, 0x63, 0xD2, 0x4C, 0x0F, 0xBF, 0x04, 0x51, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x41,
|
||||
0x8B, 0x4C, 0x39, 0x1C, 0x48, 0x03, 0xCF, 0x4A, 0x63, 0x1C, 0x81, 0x48, 0x8B, 0xCF, 0x48, 0x03,
|
||||
0xDF, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72, 0x79, 0x41, 0xFF,
|
||||
0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7, 0x44, 0x24, 0x28,
|
||||
0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0xD0,
|
||||
0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x6F,
|
||||
0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0xC8,
|
||||
0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C, 0x8D, 0x44, 0x24,
|
||||
0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9, 0x20, 0x76, 0x69,
|
||||
0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28, 0x33, 0xC9, 0xFF,
|
||||
0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7, 0x44, 0x24, 0x28,
|
||||
0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8B,
|
||||
0xCF, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48,
|
||||
0x83, 0xC4, 0x30, 0x5F, 0xC3
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -102,4 +103,4 @@ int32_t main()
|
||||
|
||||
return 0;
|
||||
}
|
||||
#pragma warning (pop)
|
||||
#pragma warning (pop)
|
||||
|
||||
+1
-1
Submodule premake updated: 1e3e269a7d...c4e967efc4
@@ -4,7 +4,8 @@ project(ProjectName)
|
||||
--Settings
|
||||
kind "ConsoleApp"
|
||||
language "C"
|
||||
flags { "StaticRuntime", "FatalWarnings" }
|
||||
flags { "FatalWarnings" }
|
||||
staticruntime "On"
|
||||
|
||||
defines { "_CRT_SECURE_NO_WARNINGS" }
|
||||
|
||||
@@ -46,6 +47,7 @@ filter { "configurations:Debug*" }
|
||||
filter { "configurations:Release" }
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
flags { "NoFramePointer", "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
flags { "NoBufferSecurityCheck", "NoIncrementalLink" }
|
||||
omitframepointer "On"
|
||||
editandcontinue "Off"
|
||||
symbols "On"
|
||||
|
||||
@@ -36,13 +36,13 @@ __declspec(noinline) void shellcode_template()
|
||||
IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pKernel32TableEntry->DllBase;
|
||||
|
||||
// In order to get the exported functions we need to go to the NT PE header.
|
||||
IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((uint8_t *)pDosHeader + pDosHeader->e_lfanew);
|
||||
IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((size_t)pDosHeader + pDosHeader->e_lfanew);
|
||||
|
||||
// From the NtHeader we can extract the virtual address of the export directory of this module.
|
||||
IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((uint8_t *)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((size_t)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
|
||||
// The exports directory contains both a list of function _names_ of this module and the associated _addresses_ of the functions.
|
||||
const int32_t *pNameOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfNames);
|
||||
const int32_t *pNameOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfNames);
|
||||
|
||||
// We will use this struct to store strings.
|
||||
// We are using a struct to make sure strings don't end up in another section of the executable where we wouldn't be able to address them in a different process.
|
||||
@@ -57,16 +57,22 @@ __declspec(noinline) void shellcode_template()
|
||||
int32_t i = 0;
|
||||
|
||||
// We're just extracting the first 8 bytes of the strings and compare them to `GetProcA`. We'll find it eventually.
|
||||
while (*(uint64_t *)((char *)pDosHeader + pNameOffsets[i]) != x.text0)
|
||||
while (*(uint64_t *)((size_t)pDosHeader + pNameOffsets[i]) != x.text0)
|
||||
++i;
|
||||
|
||||
// We have found the index of `GetProcAddress`.
|
||||
|
||||
// Not let's get the function offsets in order to retrieve the location of `GetProcAddress` in memory.
|
||||
const int32_t *pFunctionOffsets = (const int32_t *)((uint8_t *)pDosHeader + pExports->AddressOfFunctions);
|
||||
// The entry at an index in `AddressOfNames` corresponds to an entry at the same index in `AddressOfNameOrdinals`, which resolves the index of a given name to it's corresponding entry in `AddressOfFunctions`. (DLLs can export unnamed functions, which will not be listed in `AddressOfNames`.)
|
||||
// Let's get the function name ordinal offsets and function offsets in order to retrieve the location of `GetProcAddress` in memory.
|
||||
const int16_t *pFunctionNameOrdinalOffsets = (const int16_t *)((size_t)pDosHeader + pExports->AddressOfNameOrdinals);
|
||||
const int32_t *pFunctionOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfFunctions);
|
||||
|
||||
// Now resolve the index in `pFunctionOffsets` from `pFunctionNameOrdinalOffsets` to get the address of the desired function in memory.
|
||||
typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);
|
||||
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((uint8_t *)pDosHeader + pFunctionOffsets[i]);
|
||||
GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((size_t)pDosHeader + pFunctionOffsets[pFunctionNameOrdinalOffsets[i]]);
|
||||
|
||||
// For `kernel32.dll` this would technically work as well, because the index in `AddressOfNames` seems to always correspond to the the index in `AddressOfFunctions`, however this isn't technically correct.
|
||||
// GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((size_t)pDosHeader + pFunctionOffsets[i]);
|
||||
|
||||
// Now that we've got `GetProcAddress`, let's use it to get `LoadLibraryA`.
|
||||
|
||||
@@ -94,7 +100,7 @@ __declspec(noinline) void shellcode_template()
|
||||
|
||||
// Display a message box.
|
||||
x.text0 = 0x616C206174736148; // `Hasta la`
|
||||
x.text1 = 0x0021617473697620; // ` bista!\0`
|
||||
x.text1 = 0x0021617473697620; // ` vista!\0`
|
||||
|
||||
// MessageBoxA(NULL, "Hasta la vista", "", MB_OK);
|
||||
pMessageBoxA(NULL, (const char *)&x.text0, (const char *)&x.text1 + 7, MB_OK);
|
||||
|
||||
Reference in New Issue
Block a user