Skip to content

Instantly share code, notes, and snippets.

@valerysntx
Last active October 15, 2015 23:03
Show Gist options
  • Save valerysntx/94334eba1d1ac35cfeed to your computer and use it in GitHub Desktop.
Save valerysntx/94334eba1d1ac35cfeed to your computer and use it in GitHub Desktop.
x86 host x64
#ifndef _OS_STRUCTS_H_
#define _OS_STRUCTS_H_
namespace WOW64
{
#pragma pack (1)
typedef struct _LIST_ENTRY64
{
union
{
DWORD64 _Flink;
LIST_ENTRY64* Flink;
};
union
{
DWORD64 _Blink;
LIST_ENTRY64* Blink;
};
} LIST_ENTRY64;
typedef struct UNICODE_STRING64
{
WORD Length;
WORD MaximumLength;
DWORD alignment;
union
{
DWORD64 _Buffer;
WORD* Buffer;
};
} UNICODE_STRING64;
typedef struct _ANSI_STRING64
{
WORD Length;
WORD MaximumLength;
DWORD alignment;
union
{
DWORD64 _Buffer;
CHAR* Buffer;
};
} ANSI_STRING64;
typedef struct _LDR_DATA_TABLE_ENTRY64
{
LIST_ENTRY64 InLoadOrderLinks;
LIST_ENTRY64 InMemoryOrderLinks;
LIST_ENTRY64 InInitializationOrderLinks;
DWORD64 DllBase;
DWORD64 EntryPoint;
DWORD64 SizeOfImage;
UNICODE_STRING64 FullDllName;
UNICODE_STRING64 BaseDllName;
/*
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 Flags : Uint4B
+0x06c LoadCount : Uint2B
+0x06e TlsIndex : Uint2B
+0x070 HashLinks : _LIST_ENTRY
+0x070 SectionPointer : Ptr64 Void
+0x078 CheckSum : Uint4B
+0x080 TimeDateStamp : Uint4B
+0x080 LoadedImports : Ptr64 Void
+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
+0x090 PatchInformation : Ptr64 Void
+0x098 ForwarderLinks : _LIST_ENTRY
+0x0a8 ServiceTagLinks : _LIST_ENTRY
+0x0b8 StaticLinks : _LIST_ENTRY
+0x0c8 ContextInformation : Ptr64 Void
+0x0d0 OriginalBase : Uint8B
*/
} LDR_DATA_TABLE_ENTRY64;
typedef struct _PEB_LDR_DATA64
{
DWORD Length;
DWORD Initialized;
DWORD64 SsHandle;
LIST_ENTRY64 InLoadOrderModuleList;
LIST_ENTRY64 InMemoryOrderModuleList;
LIST_ENTRY64 InInitializationOrderModuleList;
DWORD64 EntryInProgress;
DWORD64 ShutdownInProgress;
DWORD64 ShutdownThreadId;
/*
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr64 Void
+0x010 InLoadOrderModuleList : _LIST_ENTRY
+0x020 InMemoryOrderModuleList : _LIST_ENTRY
+0x030 InInitializationOrderModuleList : _LIST_ENTRY
+0x040 EntryInProgress : Ptr64 Void
+0x048 ShutdownInProgress : UChar
+0x050 ShutdownThreadId : Ptr64 Void
*/
} PEB_LDR_DATA64;
typedef struct _PEB64
{
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE BitField;
DWORD Reserved1;
DWORD64 Mutant;
DWORD64 ImageBaseAddress;
union
{
DWORD64 _Ldr;
PEB_LDR_DATA64* Ldr;
};
DWORD64 ProcessParameters;
DWORD64 SubSystemData;
DWORD64 ProcessHeap;
DWORD64 FastPebLock;
DWORD64 AtlThunkSListPtr;
DWORD64 IFEOKey;
DWORD CrossProcessFlags;
DWORD Reserved2;
DWORD64 UserSharedInfoPtr; //KernelCallbackTable
DWORD SystemReserved;
DWORD AtlThunkSListPtr32;
DWORD64 ApiSetMap;
DWORD TlsExpansionCounter;
DWORD Reserved3;
DWORD64 TlsBitmap;
DWORD TlsBitmapBits;
DWORD Reserved4;
DWORD64 ReadOnlySharedMemoryBase;
DWORD64 HotpatchInformation;
DWORD64 ReadOnlyStaticServerData;
DWORD64 AnsiCodePageData;
DWORD64 OemCodePageData;
DWORD64 UnicodeCaseTableData;
DWORD NumberOfProcessors;
DWORD NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
DWORD64 HeapSegmentReserve;
DWORD64 HeapSegmentCommit;
DWORD64 HeapDeCommitTotalFreeThreshold;
DWORD64 HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
DWORD64 ProcessHeaps;
DWORD64 GdiSharedHandleTable;
DWORD64 ProcessStarterHelper;
DWORD GdiDCAttributeList;
DWORD Reserved5;
DWORD64 LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
DWORD ImageSubsystemMinorVersion;
DWORD Reserved6;
DWORD64 ActiveProcessAffinityMask;
DWORD GdiHandleBuffer;
DWORD Reserved7[59];
DWORD64 PostProcessInitRoutine;
DWORD64 TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits;
DWORD Reserved8[31];
DWORD SessionId;
DWORD Reserved9;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
DWORD64 pShimData;
DWORD64 AppCompatInfo;
UNICODE_STRING CSDVersion;
//DWORD Reserved10;
DWORD64 ActivationContextData;
DWORD64 ProcessAssemblyStorageMap;
DWORD64 SystemDefaultActivationContextData;
DWORD64 SystemAssemblyStorageMap;
DWORD64 MinimumStackCommit;
DWORD64 FlsCallback;
LIST_ENTRY FlsListHead;
DWORD64 FlsBitmap;
DWORD FlsBitmapBits;
DWORD Reserved11[3];
DWORD FlsHighIndex;
DWORD Reserved12;
DWORD64 WerRegistrationData;
DWORD64 WerShipAssertPtr;
DWORD64 pContextData;
DWORD64 pImageHeaderHash;
DWORD TracingFlags;
} PEB64;
typedef struct _EXCEPTION_REGISTRATION_RECORD64
{
DWORD64 Next;
DWORD64 Handler;
} EXCEPTION_REGISTRATION_RECORD64;
/*
//defined in winternl.h
typedef struct _NT_TIB64
{
DWORD64 ExceptionList;
DWORD64 StackBase;
DWORD64 StackLimit;
DWORD64 SubSystemTib;
DWORD64 FiberData;
DWORD64 ArbitraryUserPointer;
DWORD64 Self;
} NT_TIB64;
*/
typedef struct _CLIENT_ID64
{
DWORD64 UniqueProcess;
DWORD64 UniqueThread;
} CLIENT_ID64;
typedef struct _TEB64
{
_NT_TIB64 NtTib;
DWORD64 EnvironmentPointer;
_CLIENT_ID64 ClientId;
DWORD64 ActiveRpcHandle;
DWORD64 ThreadLocalStoragePointer;
union
{
DWORD64 _ProcessEnvironmentBlock;
PEB64* ProcessEnvironmentBlock;
};
/*
+0x000 NtTib : _NT_TIB
+0x038 EnvironmentPointer : Ptr64 Void
+0x040 ClientId : _CLIENT_ID
+0x050 ActiveRpcHandle : Ptr64 Void
+0x058 ThreadLocalStoragePointer : Ptr64 Void
+0x060 ProcessEnvironmentBlock : Ptr64 _PEB
+0x068 LastErrorValue : Uint4B
+0x06c CountOfOwnedCriticalSections : Uint4B
+0x070 CsrClientThread : Ptr64 Void
+0x078 Win32ThreadInfo : Ptr64 Void
+0x080 User32Reserved : [26] Uint4B
+0x0e8 UserReserved : [5] Uint4B
+0x100 WOW32Reserved : Ptr64 Void
+0x108 CurrentLocale : Uint4B
+0x10c FpSoftwareStatusRegister : Uint4B
+0x110 SystemReserved1 : [54] Ptr64 Void
+0x2c0 ExceptionCode : Int4B
+0x2c8 ActivationContextStackPointer : Ptr64 _ACTIVATION_CONTEXT_STACK
+0x2d0 SpareBytes : [24] UChar
+0x2e8 TxFsContext : Uint4B
+0x2f0 GdiTebBatch : _GDI_TEB_BATCH
+0x7d8 RealClientId : _CLIENT_ID
+0x7e8 GdiCachedProcessHandle : Ptr64 Void
+0x7f0 GdiClientPID : Uint4B
+0x7f4 GdiClientTID : Uint4B
+0x7f8 GdiThreadLocalInfo : Ptr64 Void
+0x800 Win32ClientInfo : [62] Uint8B
+0x9f0 glDispatchTable : [233] Ptr64 Void
+0x1138 glReserved1 : [29] Uint8B
+0x1220 glReserved2 : Ptr64 Void
+0x1228 glSectionInfo : Ptr64 Void
+0x1230 glSection : Ptr64 Void
+0x1238 glTable : Ptr64 Void
+0x1240 glCurrentRC : Ptr64 Void
+0x1248 glContext : Ptr64 Void
+0x1250 LastStatusValue : Uint4B
+0x1258 StaticUnicodeString : _UNICODE_STRING
+0x1268 StaticUnicodeBuffer : [261] Wchar
+0x1478 DeallocationStack : Ptr64 Void
+0x1480 TlsSlots : [64] Ptr64 Void
+0x1680 TlsLinks : _LIST_ENTRY
+0x1690 Vdm : Ptr64 Void
+0x1698 ReservedForNtRpc : Ptr64 Void
+0x16a0 DbgSsReserved : [2] Ptr64 Void
+0x16b0 HardErrorMode : Uint4B
+0x16b8 Instrumentation : [11] Ptr64 Void
+0x1710 ActivityId : _GUID
+0x1720 SubProcessTag : Ptr64 Void
+0x1728 EtwLocalData : Ptr64 Void
+0x1730 EtwTraceData : Ptr64 Void
+0x1738 WinSockData : Ptr64 Void
+0x1740 GdiBatchCount : Uint4B
+0x1744 CurrentIdealProcessor : _PROCESSOR_NUMBER
+0x1744 IdealProcessorValue : Uint4B
+0x1744 ReservedPad0 : UChar
+0x1745 ReservedPad1 : UChar
+0x1746 ReservedPad2 : UChar
+0x1747 IdealProcessor : UChar
+0x1748 GuaranteedStackBytes : Uint4B
+0x1750 ReservedForPerf : Ptr64 Void
+0x1758 ReservedForOle : Ptr64 Void
+0x1760 WaitingOnLoaderLock : Uint4B
+0x1768 SavedPriorityState : Ptr64 Void
+0x1770 SoftPatchPtr1 : Uint8B
+0x1778 ThreadPoolData : Ptr64 Void
+0x1780 TlsExpansionSlots : Ptr64 Ptr64 Void
+0x1788 DeallocationBStore : Ptr64 Void
+0x1790 BStoreLimit : Ptr64 Void
+0x1798 MuiGeneration : Uint4B
+0x179c IsImpersonating : Uint4B
+0x17a0 NlsCache : Ptr64 Void
+0x17a8 pShimData : Ptr64 Void
+0x17b0 HeapVirtualAffinity : Uint4B
+0x17b8 CurrentTransactionHandle : Ptr64 Void
+0x17c0 ActiveFrame : Ptr64 _TEB_ACTIVE_FRAME
+0x17c8 FlsData : Ptr64 Void
+0x17d0 PreferredLanguages : Ptr64 Void
+0x17d8 UserPrefLanguages : Ptr64 Void
+0x17e0 MergedPrefLanguages : Ptr64 Void
+0x17e8 MuiImpersonation : Uint4B
+0x17ec CrossTebFlags : Uint2B
+0x17ec SpareCrossTebBits : Pos 0, 16 Bits
+0x17ee SameTebFlags : Uint2B
+0x17ee SafeThunkCall : Pos 0, 1 Bit
+0x17ee InDebugPrint : Pos 1, 1 Bit
+0x17ee HasFiberData : Pos 2, 1 Bit
+0x17ee SkipThreadAttach : Pos 3, 1 Bit
+0x17ee WerInShipAssertCode : Pos 4, 1 Bit
+0x17ee RanProcessInit : Pos 5, 1 Bit
+0x17ee ClonedThread : Pos 6, 1 Bit
+0x17ee SuppressDebugMsg : Pos 7, 1 Bit
+0x17ee DisableUserStackWalk : Pos 8, 1 Bit
+0x17ee RtlExceptionAttached : Pos 9, 1 Bit
+0x17ee InitialThread : Pos 10, 1 Bit
+0x17ee SpareSameTebBits : Pos 11, 5 Bits
+0x17f0 TxnScopeEnterCallback : Ptr64 Void
+0x17f8 TxnScopeExitCallback : Ptr64 Void
+0x1800 TxnScopeContext : Ptr64 Void
+0x1808 LockCount : Uint4B
+0x180c SpareUlong0 : Uint4B
+0x1810 ResourceRetValue : Ptr64 Void
*/
} TEB64;
#pragma pack()
};
#endif //_OS_STRUCTS_H_
#include <cstdio>
#include <windows.h>
#include <winternl.h>
#include "os_structs.h"
#define EMIT(a) __asm __emit (a)
#define X64_Start_with_CS(_cs) \
{ \
EMIT(0x6A) EMIT(_cs) /* push _cs */ \
EMIT(0xE8) EMIT(0) EMIT(0) EMIT(0) EMIT(0) /* call $+5 */ \
EMIT(0x83) EMIT(4) EMIT(0x24) EMIT(5) /* add dword [esp], 5 */ \
EMIT(0xCB) /* retf */ \
}
#define X64_End_with_CS(_cs) \
{ \
EMIT(0xE8) EMIT(0) EMIT(0) EMIT(0) EMIT(0) /* call $+5 */ \
EMIT(0xC7) EMIT(0x44) EMIT(0x24) EMIT(4) EMIT(_cs) EMIT(0) EMIT(0) EMIT(0) /* mov dword [rsp + 4], _cs */ \
EMIT(0x83) EMIT(4) EMIT(0x24) EMIT(0xD) /* add dword [rsp], 0xD */ \
EMIT(0xCB) /* retf */ \
}
#define X64_Start() X64_Start_with_CS(0x33)
#define X64_End() X64_End_with_CS(0x23)
#define _RAX 0
#define _RCX 1
#define _RDX 2
#define _RBX 3
#define _RSP 4
#define _RBP 5
#define _RSI 6
#define _RDI 7
#define _R8 8
#define _R9 9
#define _R10 10
#define _R11 11
#define _R12 12
#define _R13 13
#define _R14 14
#define _R15 15
#define X64_Push(r) EMIT(0x48 | ((r) >> 3)) EMIT(0x50 | ((r) & 7))
#define X64_Pop(r) EMIT(0x48 | ((r) >> 3)) EMIT(0x58 | ((r) & 7))
//to fool M$ inline asm compiler I'm using 2 DWORDs instead of DWORD64
//use of DWORD64 will generate wrong 'pop word ptr[]' and it will break stack
union reg64
{
DWORD dw[2];
DWORD64 v;
};
WOW64::TEB64* getTEB64()
{
reg64 reg;
reg.v = 0;
X64_Start();
//R12 register should always contain pointer to TEB64 in WoW64 processes
X64_Push(_R12);
//below pop will pop QWORD from stack, as we're in x64 mode now
__asm pop reg.dw[0]
X64_End();
//upper 32 bits should be always 0 in WoW64 processes
if (reg.dw[1] != 0)
return 0;
return (WOW64::TEB64*)reg.dw[0];
}
DWORD getNTDLL64()
{
static DWORD ntdll64 = 0;
if (ntdll64 != 0)
return ntdll64;
WOW64::TEB64* teb64 = getTEB64();
WOW64::PEB64* peb64 = teb64->ProcessEnvironmentBlock;
WOW64::PEB_LDR_DATA64* ldr = peb64->Ldr;
printf("TEB: %08X\n", (DWORD)teb64);
printf("PEB: %08X\n", (DWORD)peb64);
printf("LDR: %08X\n", (DWORD)ldr);
printf("Loaded modules:\n");
WOW64::LDR_DATA_TABLE_ENTRY64* head = (WOW64::LDR_DATA_TABLE_ENTRY64*)ldr->InLoadOrderModuleList.Flink;
do
{
printf(" %ws\n", head->BaseDllName.Buffer);
if (memcmp(head->BaseDllName.Buffer, L"ntdll.dll", head->BaseDllName.Length) == 0)
ntdll64 = (DWORD)head->DllBase;
head = (WOW64::LDR_DATA_TABLE_ENTRY64*)head->InLoadOrderLinks.Flink;
}
while (head != (WOW64::LDR_DATA_TABLE_ENTRY64*)&ldr->InLoadOrderModuleList);
printf("NTDLL x64: %08X\n", ntdll64);
return ntdll64;
}
DWORD getLdrGetProcedureAddress()
{
BYTE* modBase = (BYTE*)getNTDLL64();
IMAGE_NT_HEADERS64* inh = (IMAGE_NT_HEADERS64*)(modBase + ((IMAGE_DOS_HEADER*)modBase)->e_lfanew);
IMAGE_DATA_DIRECTORY& idd = inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (idd.VirtualAddress == 0)
return 0;
IMAGE_EXPORT_DIRECTORY* ied = (IMAGE_EXPORT_DIRECTORY*)(modBase + idd.VirtualAddress);
DWORD* rvaTable = (DWORD*)(modBase + ied->AddressOfFunctions);
WORD* ordTable = (WORD*)(modBase + ied->AddressOfNameOrdinals);
DWORD* nameTable = (DWORD*)(modBase + ied->AddressOfNames);
//lazy search, there is no need to use binsearch for just one function
for (DWORD i = 0; i < ied->NumberOfFunctions; i++)
{
if (strcmp((char*)modBase + nameTable[i], "LdrGetProcedureAddress"))
continue;
else
return (DWORD)(modBase + rvaTable[ordTable[i]]);
}
return 0;
}
DWORD64 X64Call(DWORD func, int argC, ...)
{
va_list args;
va_start(args, argC);
DWORD64 _rcx = (argC > 0) ? argC--, va_arg(args, DWORD64) : 0;
DWORD64 _rdx = (argC > 0) ? argC--, va_arg(args, DWORD64) : 0;
DWORD64 _r8 = (argC > 0) ? argC--, va_arg(args, DWORD64) : 0;
DWORD64 _r9 = (argC > 0) ? argC--, va_arg(args, DWORD64) : 0;
reg64 _rax;
_rax.v = 0;
DWORD64 restArgs = (DWORD64)&va_arg(args, DWORD64);
//conversion to QWORD for easier use in inline assembly
DWORD64 _argC = argC;
DWORD64 _func = func;
DWORD back_esp = 0;
__asm
{
;//keep original esp in back_esp variable
mov back_esp, esp
;//align esp to 8, without aligned stack some syscalls may return errors !
and esp, 0xFFFFFFF8
X64_Start();
;//fill first four arguments
push _rcx
X64_Pop(_RCX);
push _rdx
X64_Pop(_RDX);
push _r8
X64_Pop(_R8);
push _r9
X64_Pop(_R9);
push edi
push restArgs
X64_Pop(_RDI);
push _argC
X64_Pop(_RAX);
;//put rest of arguments on the stack
test eax, eax
jz _ls_e
lea edi, dword ptr [edi + 8*eax - 8]
_ls:
test eax, eax
jz _ls_e
push dword ptr [edi]
sub edi, 8
sub eax, 1
jmp _ls
_ls_e:
;//create stack space for spilling registers
sub esp, 0x20
call _func
;//cleanup stack
push _argC
X64_Pop(_RCX);
lea esp, dword ptr [esp + 8*ecx + 0x20]
pop edi
//set return value
X64_Push(_RAX);
pop _rax.dw[0]
X64_End();
mov esp, back_esp
}
return _rax.v;
}
DWORD64 GetProcAddress64(DWORD module, char* funcName)
{
static DWORD _LdrGetProcedureAddress = 0;
if (_LdrGetProcedureAddress == 0)
{
_LdrGetProcedureAddress = getLdrGetProcedureAddress();
printf("LdrGetProcedureAddress: %08X\n", _LdrGetProcedureAddress);
if (_LdrGetProcedureAddress == 0)
return 0;
}
WOW64::ANSI_STRING64 fName = { 0 };
fName.Buffer = funcName;
fName.Length = strlen(funcName);
fName.MaximumLength = fName.Length + 1;
DWORD64 funcRet = 0;
X64Call(_LdrGetProcedureAddress, 4,
(DWORD64)module, (DWORD64)&fName,
(DWORD64)0, (DWORD64)&funcRet);
printf("%s: %08X\n", funcName, (DWORD)funcRet);
return funcRet;
}
int wmain();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int argc = 0;
int ret = 0;
LPWSTR* argv = CommandLineToArgvW(GetCommandLine(), &argc);
if (argv)
{
ret = wmain();
LocalFree(argv);
}
return ret;
}
int wmain()
{
DWORD hNtdll = getNTDLL64();
DWORD tmp = (DWORD)GetProcAddress64(hNtdll, "A_SHAInit");
system("pause");
return 0;
}
@valerysntx
Copy link
Author

x86 host of x64

DWORD hNtdll = getNTDLL64();
DWORD tmp = (DWORD)GetProcAddress64(hNtdll, "A_SHAInit"); //load x64 ntdll module and import 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment