Last active
August 27, 2022 08:37
-
-
Save pgkt04/819c8654507012660818f0db9af4d87e to your computer and use it in GitHub Desktop.
calling x64 bit syscall with their ordinals
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// make syscalls from their ordinals | |
#include <Windows.h> | |
#include <stdio.h> | |
#include <cstdint> | |
#include <vector> | |
struct syscall_bytes { | |
uint8_t | |
header[0x4] , | |
index , pad[0x3]; | |
}; | |
typedef NTSTATUS( NTAPI* fn_NtCreateThreadEx ) | |
( | |
OUT PHANDLE hThread , | |
IN ACCESS_MASK DesiredAccess , | |
IN PVOID ObjectAttributes , | |
IN HANDLE ProcessHandle , | |
IN PVOID lpStartAddress , | |
IN PVOID lpParameter , | |
IN ULONG Flags , | |
IN SIZE_T StackZeroBits , | |
IN SIZE_T SizeOfStackCommit , | |
IN SIZE_T SizeOfStackReserve , | |
OUT PVOID lpBytesBuffer); | |
void test_thread( ) { | |
MessageBoxA( NULL , "Thread Created" , "Success" , MB_OK ); | |
} | |
int main( ) | |
{ | |
// since windows automatically loads ntdll we can directly reference it | |
auto ntdll = GetModuleHandleA( "ntdll.dll" ); | |
if (!ntdll) { | |
printf( "ntdll.dll not loaded\n" ); | |
return 0; | |
} | |
auto syscall = *(syscall_bytes*)(GetProcAddress( ntdll , "NtCreateThreadEx" )); | |
// build the stub dynmically | |
std::vector<uint8_t> syscall_stub; | |
printf( "Setting up stub\n" ); | |
// write the header infomation | |
for (auto op_code : syscall.header) { | |
syscall_stub.push_back( op_code ); | |
} | |
// write the ordinal | |
syscall_stub.push_back( syscall.index ); | |
// complete the padding | |
for (auto op_code : syscall.pad) { | |
syscall_stub.push_back( op_code ); | |
} | |
// write instructions to call syscall ordinal | |
uint8_t call_syscall[] = { 0x0F, 0x05 }; | |
syscall_stub.insert( | |
// push to the end | |
syscall_stub.end( ) , | |
// instructions | |
std::begin( call_syscall ) , | |
// count | |
std::end( call_syscall ) ); | |
// write the exit | |
syscall_stub.push_back( 0xC3 ); | |
// 2. allocate page for syscall instructions (stub you wrote in the previous step) | |
auto page_addr = VirtualAlloc( | |
nullptr , | |
sizeof( syscall_stub ) , | |
MEM_RESERVE | MEM_COMMIT , | |
PAGE_EXECUTE_READWRITE | |
); | |
printf( "writing stub to page\n" ); | |
// write the stub to the page allocated | |
memcpy( page_addr , syscall_stub.data( ) , sizeof( syscall_stub ) ); | |
auto nt_create_thread = fn_NtCreateThreadEx( page_addr ); | |
printf( "calling nt_create_thread\n" ); | |
HANDLE hThread = nullptr; | |
auto status = nt_create_thread( | |
&hThread , | |
THREAD_ALL_ACCESS , | |
nullptr , | |
GetCurrentProcess( ) , | |
(LPTHREAD_START_ROUTINE)(test_thread) , | |
nullptr , NULL , 0 , 0 , 0 , nullptr ); | |
if (status == 0x00000000) | |
printf( "status: success\n" ); | |
else | |
printf( "status: %X \n" , status ); | |
// Finished syscall, freeing it... | |
VirtualFree( page_addr , NULL , MEM_RELEASE ); | |
system( "pause" ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment