Using AddressOfNameOrdinals when resolving the function name index to the corresponding address

This commit is contained in:
Christoph Stiller
2021-04-14 17:39:52 +02:00
parent 2af6e6df17
commit 2f7fc0f9e1
8 changed files with 127 additions and 100 deletions
+68 -54
View File
@@ -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
View File
@@ -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 -2
View File
@@ -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 -2
View File
@@ -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"
+21 -20
View File
@@ -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 -2
View File
@@ -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"
+14 -8
View File
@@ -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);