Skip to content

Instantly share code, notes, and snippets.

@qtkite
Last active August 27, 2022 08:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save qtkite/819c8654507012660818f0db9af4d87e to your computer and use it in GitHub Desktop.
Save qtkite/819c8654507012660818f0db9af4d87e to your computer and use it in GitHub Desktop.
calling x64 bit syscall with their ordinals
// 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