Hello,
Knowing that inline assembly __asm not is supported in Visual Studio for x64 projects i decided that the better solution can be a translation of inline assembly to C++.
But my knowledge is very little with Assembly.
Then someone could help me with this?
Here is the code ( this program is a Unhooker to Apis Messages ) compiled with VS2012 Ultimate:
EnumWindowsHookEx.cpp
// EnumWindowsHookEx.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "EnumWindowsHooks.h"
#pragma comment(lib, "ntdll")
int __cdecl main(int argc, char **argv)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PVOID ImageBase;
ULONG DllCharacteristics = 0;
PVOID User32InitializeImmEntryTable = NULL;
UNICODE_STRING DllName;
ANSI_STRING ProcedureName;
ULONG i;
ULONG UserDelta = 0;
ULONG HandleEntries = 0;
SHARED_INFO *SharedInfo = NULL;
HANDLE_ENTRY *UserHandleTable = NULL;
HOOK *HookInfo = NULL;
__try
{
system("cls");
RtlInitUnicodeString(
&DllName,
L"user32");
NtStatus = LdrLoadDll(
NULL, // DllPath
&DllCharacteristics, // DllCharacteristics
&DllName, // DllName
&ImageBase); // DllHandle
if(NtStatus == STATUS_SUCCESS)
{
RtlInitAnsiString(
&ProcedureName,
"User32InitializeImmEntryTable");
NtStatus = LdrGetProcedureAddress(
ImageBase, // DllHandle
&ProcedureName, // ProcedureName
0, // ProcedureNumber OPTIONAL
(PVOID*)&User32InitializeImmEntryTable); // ProcedureAddress
if(NtStatus == STATUS_SUCCESS)
{
__asm
{
mov esi, User32InitializeImmEntryTable
test esi, esi
jz __exit2
mov ecx, 0x80
__loop:
dec ecx
test ecx, ecx
jz __exit1
lodsb
cmp al, 0x50
jnz __loop
lodsb
cmp al, 0x68
jnz __loop
lodsd
mov SharedInfo, eax
jmp __exit2
__exit1:
mov SharedInfo, ecx
__exit2:
sub eax, eax
mov eax, fs:[eax+0x18]
lea eax, [eax+0x06CC]
mov eax, [eax+0x001C]
mov UserDelta, eax
}
HandleEntries = *((ULONG *)((ULONG)SharedInfo->ServerInfo + 8));
printf(
" +--------------------------------------------------------------------+\n"
" | SHARED_INFO - %.8X |\n"
" +--------------------------------------------------------------------+\n"
" | ServerInfo - %.8X |\n"
" | HandleEntryList - %.8X |\n"
" | HandleEntries - %.8X |\n"
" | DisplayInfo - %.8X |\n"
" | SharedDelta - %.8X |\n"
" | UserDelta - %.8X |\n"
" +--------------------------------------------------------------------+\n\n",
SharedInfo,
SharedInfo->ServerInfo,
SharedInfo->HandleEntryList,
HandleEntries,
SharedInfo->DisplayInfo,
SharedInfo->SharedDelta,
UserDelta);
UserHandleTable = (HANDLE_ENTRY *)SharedInfo->HandleEntryList;
for(i=0; i<HandleEntries; i++)
{
if(UserHandleTable[i].Type == TYPE_HOOK)
{
__try
{
HookInfo = (HOOK *)((ULONG)UserHandleTable[i].Head - UserDelta);
printf(
" +--------------------------------------------------------------------+\n"
" | HOOK - %.8X |\n"
" +--------------------------------------------------------------------+\n"
" | Handle - %.8X |\n"
" | LockObj - %.8X |\n"
" | ThreadInfo- %.8X |\n"
" | Desktop1 - %.8X |\n"
" | Self - %.8X |\n"
" | NextHook - %.8X |\n"
" | HookType - %.8X |\n"
" | FunctionAddress - %.8X |\n"
" | Flags - %.8X |\n"
" | ModuleHandle - %.8X |\n"
" | Hooked - %.8X |\n"
" | Desktop2 - %.8X |\n"
" +--------------------------------------------------------------------+\n\n",
(ULONG)UserHandleTable[i].Head - UserDelta,
HookInfo->Handle,
HookInfo->LockObj,
HookInfo->ThreadInfo,
HookInfo->Desktop1,
HookInfo->Self,
HookInfo->NextHook,
HookInfo->HookType,
HookInfo->FunctionAddress,
HookInfo->Flags,
HookInfo->ModuleHandle,
HookInfo->Hooked,
HookInfo->Desktop2);
UnhookWindowsHookEx((HHOOK)HookInfo->Handle);
}
__except(EXCEPTION_EXECUTE_HANDLER) {}
}
}
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf(">> main - %.8X\n", GetExceptionCode());
//return GetExceptionCode();
}
system("pause");
return FALSE;
}
EnumWindowsHooks.h
#ifndef __ENUM_WINDOWS_HOOKS__
#define __ENUM_WINDOWS_HOOKS__
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define IMP_VOID __declspec(dllimport) VOID __stdcall
#define IMP_SYSCALL __declspec(dllimport) NTSTATUS __stdcall
#define STATUS_SUCCESS 0x00000000
#define STATUS_UNSUCCESSFUL 0xC0000001
#define STATUS_INVALID_PARAMETER_1 0xC00000EF
#define STATUS_INVALID_PARAMETER_2 0xC00000F0
typedef struct ANSI_STRING
{
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
}
ANSI_STRING,
*PANSI_STRING,
**PPANSI_STRING;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}
UNICODE_STRING,
*PUNICODE_STRING,
**PPUNICODE_STRING;
#define TYPE_FREE 0
#define TYPE_WINDOW 1
#define TYPE_MENU 2
#define TYPE_CURSOR 3
#define TYPE_SETWINDOWPOS 4
#define TYPE_HOOK 5
#define TYPE_CLIPDATA 6
#define TYPE_CALLPROC 7
#define TYPE_ACCELTABLE 8
#define TYPE_DDEACCESS 9
#define TYPE_DDECONV 10
#define TYPE_DDEXACT 11
#define TYPE_MONITOR 12
#define TYPE_KBDLAYOUT 13
#define TYPE_KBDFILE 14
#define TYPE_WINEVENTHOOK 15
#define TYPE_TIMER 16
#define TYPE_INPUTCONTEXT 17
#define TYPE_CTYPES 18
#define TYPE_GENERIC 255
#define HMINDEXBITS 0x0000FFFF
#define HMUNIQSHIFT 16
#define HMUNIQBITS 0xFFFF0000
#define MAX_HANDLE_COUNT 0x8000
typedef struct _HEAD
{
HANDLE Handle;
ULONG LockObj;
}
HEAD,
*PHEAD,
**PPHEAD;
typedef struct _HANDLE_ENTRY
{
HEAD *Head;
PVOID Owner;
UCHAR Type;
UCHAR Flags;
USHORT Unique;
}
HANDLE_ENTRY,
*PHANDLE_ENTRY,
**PPHANDLE_ENTRY;
typedef struct _SHARED_INFO
{
PVOID ServerInfo;
HANDLE_ENTRY *HandleEntryList;
PVOID DisplayInfo;
ULONG SharedDelta;
}
SHARED_INFO,
*PSHARED_INFO,
**PPSHARED_INFO;
typedef struct _HOOK
{
ULONG Handle;
ULONG LockObj;
PVOID ThreadInfo;
PVOID Desktop1;
PVOID Self;
PVOID NextHook;
LONG HookType;
PVOID FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
}
HOOK,
*PHOOK,
**PPHOOK;
extern "C" IMP_SYSCALL LdrLoadDll
(
IN PWSTR DllPath OPTIONAL,
IN PULONG DllCharacteristics OPTIONAL,
IN PUNICODE_STRING DllName,
OUT PVOID *DllHandle
);
extern "C" IMP_SYSCALL LdrGetProcedureAddress
(
IN PVOID DllHandle,
IN PANSI_STRING ProcedureName OPTIONAL,
IN ULONG ProcedureNumber OPTIONAL,
OUT PVOID *ProcedureAddress
);
extern "C" IMP_VOID RtlInitAnsiString
(
IN OUT PANSI_STRING DestinationString,
IN PCSTR SourceString
);
extern "C" IMP_VOID RtlInitUnicodeString
(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
#endif
Hi Flashcoder,
First of all, welcome to the forum.
Although I´m not the most well versed around, let me dare and say I believe the BEST solution is to create an asm file that will be working side by side to your C++ project. It´s very easy to do AND a lot better than inline. You just need to call it from the C++ world as functions.
It´s pretty much straight forward, you just need to "extern" the asm function.
There are many examples in the web, check out this one:
https://www.youtube.com/watch?v=guru397zg2g (https://www.youtube.com/watch?v=guru397zg2g)
@LordAdef,
Thank you, but see that on code above exists 3 c++ variables used inside assembly code, are they:
User32InitializeImmEntryTable
SharedInfo
UserDelta
Then, how use these variables, stucts... on asm code from external .asm file?
On video suggested of Youtube, is showed only a simply method.
Hi Flash,
You must send the 3 variables to the function, defining their "sizes" in the extern declaration, in C++ world. I didn´t check the variables types, but if you have to send them as reference, "Pointers" in 32 bit masm are DWORDs, in 64 I guess they are QWORD in the masm world.
I don´t see him prototyping the asm function in the asm file, maybe you don´t need to and admit I needed to test. But if you do, it would be something like this:
AsmNirvanaFunction PROTO :QWORD, :QWORD, :QWORD
Ok LordAdef,
How be should these types:
PVOID, ULONG, Struct
typedef struct _SHARED_INFO
{
PVOID ServerInfo;
HANDLE_ENTRY *HandleEntryList;
PVOID DisplayInfo;
ULONG SharedDelta;
}
SHARED_INFO,
*PSHARED_INFO,
**PPSHARED_INFO;
--------------------------------------------------
PVOID User32InitializeImmEntryTable = NULL;
ULONG UserDelta = 0;
SHARED_INFO *SharedInfo = NULL;
respectivelly from of C++ to ASM, as parameters of AsmNirvanaFunction?
Don't bother with it, on 7x64 (at least) all the addresses are in kernel mode so you can't do anything with them when you do find the HOOKs.
EnumHooks apparently found 4437 handles
Found hook at FFFFF900C0830E20
Found hook at FFFFF900C0837610
Found hook at FFFFF900C0848840
etc..
struct tagSERVERINFO
{
ULONG srviFlags;
SIZE_T handleEntries;
};
struct tagSHAREDINFO
{
tagSERVERINFO* psi;
struct _HANDLE_ENTRY* aheList;
unsigned long HeEntrySize;
};
void EnumHooks()
{
HMODULE hUser = GetModuleHandle(L"user32.dll");
tagSHAREDINFO* pSharedData = (tagSHAREDINFO*)GetProcAddress(hUser, "gSharedInfo");
SIZE_T entrySize = pSharedData->psi->handleEntries;
printf("EnumHooks apparently found %Iu handles\n", entrySize);
TEB_7* pTeb = (TEB_7*)NtCurrentTeb();
UINT_PTR offset = pTeb->Win32ClientInfo[7];
for(ULONG i = 0; i < entrySize; ++i)
{
HANDLE_ENTRY* pHandle = &pSharedData->aheList[i];
if(pHandle->Type != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)(pHandle->pHead - offset);
if(HookInfo)
{
printf("Found hook at %p\n", HookInfo);
}
}
}
@AdeyBlue,
thank you very much by code example, but here not worked, and you also not showed complete code above.
Then i completed your code like below, but not worked :icon_confused: Comes a Access Violation in printf inside of for loop.
#include "stdafx.h"
#include <process.h>
#include <iostream>
#include <windows.h>
#include <WinNT.h>
#include "EnumWindowsHooks.h"
#pragma comment(lib, "ntdll")
using namespace std;
typedef struct _HANDLEENTRY {
PVOID phead;
PVOID pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY, *PHANDLEENTRY;
typedef struct _SERVERINFO {
WORD wRIPFlags;
WORD wSRVIFlags;
WORD wRIPPID;
WORD wRIPError;
ULONG cHandleEntries;
} SERVERINFO, *PSERVERINFO;
typedef struct _SHAREDINFO {
PSERVERINFO psi;
PHANDLEENTRY aheList;
ULONG HeEntrySize;
} SHAREDINFO, *PSHAREDINFO;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[229];
PVOID Reserved3[59];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _TEB
{
NT_TIB Tib;
PVOID EnvironmentPointer;
CLIENT_ID Cid;
PVOID ActiveRpcInfo;
PVOID ThreadLocalStoragePointer;
PPEB Peb;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG Win32ClientInfo[0x1F];
PVOID WOW32Reserved;
ULONG CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID SystemReserved1[0x36];
PVOID Spare1;
ULONG ExceptionCode;
ULONG SpareBytes1[0x28];
PVOID SystemReserved2[0xA];
ULONG GdiRgn;
ULONG GdiPen;
ULONG GdiBrush;
CLIENT_ID RealClientId;
PVOID GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocaleInfo;
PVOID UserReserved[5];
PVOID GlDispatchTable[0x118];
ULONG GlReserved1[0x1A];
PVOID GlReserved2;
PVOID GlSectionInfo;
PVOID GlSection;
PVOID GlTable;
PVOID GlCurrentRC;
PVOID GlContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[0x105];
PVOID DeallocationStack;
PVOID TlsSlots[0x40];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[0x2];
ULONG HardErrorDisabled;
PVOID Instrumentation[0x10];
PVOID WinSockData;
ULONG GdiBatchCount;
ULONG Spare2;
ULONG Spare3;
ULONG Spare4;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
PVOID StackCommit;
PVOID StackCommitMax;
PVOID StackReserved;
} TEB, *PTEB;
void EnumHooks()
{
HMODULE hUser = GetModuleHandle(L"user32.dll");
PSHAREDINFO gSharedInfo=NULL;
PHANDLEENTRY aheList=NULL;
ULONG_PTR k;
gSharedInfo = (PSHAREDINFO)GetProcAddress(hUser, "gSharedInfo");
aheList = gSharedInfo->aheList;
k = gSharedInfo->psi->cHandleEntries;
printf("EnumHooks apparently found %Iu handles\n", k);
PTEB pTeb = (PTEB)NtCurrentTeb();
UINT_PTR offset = pTeb->Win32ClientInfo[7];
for(ULONG i = 0; i < k; ++i)
{
HANDLEENTRY* pHandle = &aheList[i];
if(pHandle->bType != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)((PVOID*)pHandle->phead - offset);
if(HookInfo)
{
//printf("Found hook at %p\n", HookInfo);
}
}
}
It works only in native environment?
In WOW64 PHANDLEENTRY is 0 and HeEntrySize is trash? It should be sizeof(HANDLEENTRY)?
Quote from: TWell on March 21, 2017, 07:55:35 PM
It works only in native environment?
In WOW64 PHANDLEENTRY is 0 and HeEntrySize is trash? It should be sizeof(HANDLEENTRY)?
@TWell,
here are all returned values:
Environment of test:
VS2012 Ultimate,
Debug mode,
Win32 app,
Windows 7 x64 Home Premium.
(http://image.prntscr.com/image/eb6b8b6a110c4eb5b804404dfd7356ac.png)
(http://image.prntscr.com/image/1f66737aa3fc44d3bae409efce49ef5a.png)
(http://image.prntscr.com/image/f022a3357dab465c866bbff575bc2167.png)
So it is a WOW64 problem, gSharedInfo is 64-bit version in 32bit program too?
That aheList is 0 as pointers truncated.
if gSharedInfo use something like this, offset are more correct and HeEntrySize is 18h/24typedef struct _SHAREDINFO64 {
ULONGLONG psi;
ULONGLONG aheList;
ULONG HeEntrySize;
// ...
} SHAREDINFO64, *PSHAREDINFO64;
EDIT:
In main program something like this:
if (pSharedInfo->HeEntrySize == sizeof(HANDLEENTRY)) {// native
EnumHandles(pSharedInfo);
} else { // in WOW64
EnumHandles3264(pSharedInfo);
}
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int printf(const char * restrict format, ...);
typedef struct _HANDLEENTRY64 {
ULONGLONG pHead;
ULONGLONG pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY64, *PHANDLEENTRY64;
typedef struct _SHAREDINFO64 {
ULONGLONG psi;
ULONGLONG aheList;
ULONG HeEntrySize;
ULONGLONG pDispInfo;
ULONG_PTR ulSharedDelta;
ULONG_PTR awmControl;
ULONG_PTR DefWindowMsgs;
ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO64, *PSHAREDINFO64;
typedef struct _HOOK
{
ULONGLONG Handle;
ULONG LockObj;
ULONGLONG ThreadInfo;
ULONGLONG Desktop1;
ULONGLONG Self;
ULONGLONG NextHook;
LONG HookType;
ULONGLONG FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
} HOOK,*PHOOK,**PPHOOK;
#define TYPE_HOOK 5
void EnumHandles3264(SHAREDINFO64 *pSharedInfo64)
{
struct _TEB* pTeb = NtCurrentTeb();
ULONGLONG offset = *(ULONGLONG*)(((BYTE*)pTeb)-0x2000+0x800+0x28); // pTeb->Win32ClientInfo.ulClientDelta
ULONG cHandleEntries = *((ULONG *) ((ULONG)pSharedInfo64->psi + 8));
HANDLEENTRY64 *Handle = (HANDLEENTRY64*)pSharedInfo64->aheList;
for(ULONG i = 0; i < cHandleEntries; ++i)
{
HANDLEENTRY64* pHandle = Handle++;
if(pHandle->bType != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)((UINT_PTR)pHandle->pHead - offset);
if(HookInfo)
{
printf("Found hook at %p", HookInfo);
printf(" Handle: %08llX %2d %d\n", HookInfo->Handle, HookInfo->HookType, HookInfo->Flags);
}
}
}
native EnumHandles()#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int printf(const char * restrict format, ...);
typedef struct _HOOK
{
HANDLE Handle;
ULONG LockObj;
PVOID ThreadInfo;
PVOID Desktop1;
PVOID Self;
PVOID NextHook;
LONG HookType;
PVOID FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
ULONG bitField;
} HOOK, *PHOOK, **PPHOOK;
#define TYPE_HOOK 5
typedef struct _HANDLEENTRY {
PVOID pHead;
PVOID pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY, *PHANDLEENTRY;
typedef struct _SERVERINFO {
WORD wRIPFlags;
WORD wSRVIFlags;
WORD wRIPPID;
WORD wRIPError;
ULONG cHandleEntries;
// incomplete
} SERVERINFO, *PSERVERINFO;
typedef struct _SHAREDINFO {
PSERVERINFO psi;
PHANDLEENTRY aheList;
ULONG HeEntrySize;
ULONG_PTR pDispInfo;
ULONG_PTR ulSharedDelta;
ULONG_PTR awmControl;
ULONG_PTR DefWindowMsgs;
ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO, *PSHAREDINFO;
void EnumHandles(SHAREDINFO *pSharedInfo)
{
struct _TEB* pTeb = NtCurrentTeb();
#ifdef _WIN64
ULONGLONG offset = *(ULONGLONG*)(((BYTE*)pTeb)+0x800+0x28); // pTeb->Win32ClientInfo.ulClientDelta
#else
ULONG offset = *(ULONG*)(((BYTE*)pTeb)+0x6CC+0x1C); // pTeb->Win32ClientInfo.ulClientDelta
#endif
ULONG cHandleEntries = pSharedInfo->psi->cHandleEntries;
HANDLEENTRY *Handle = (HANDLEENTRY*)pSharedInfo->aheList;
for(ULONG i = 0; i < cHandleEntries; ++i)
{
HANDLEENTRY* pHandle = Handle++;
if(pHandle->bType != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)((UINT_PTR)pHandle->pHead - offset);
if(HookInfo)
{
printf("Found hook at %p", HookInfo);
printf(" Handle: %08llX %2d %d\n", HookInfo->Handle, HookInfo->HookType, HookInfo->Flags);
}
}
}
@TWell,
i have a new code ( based in this link: http://www.netfairy.net/?post=238 (http://www.netfairy.net/?post=238) ), and this trouble was solved :eusa_dance:.
Now i'm trying print the Handle of hook, but i getting a Access Violation :icon_confused:.
TEB struct still is the same got of this link: http://b4you.net/blog/tag/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D?page=2/RK=0/RS=OnSynb5PqLHcGlxDbsJRgEqfmuM- (http://b4you.net/blog/tag/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D?page=2/RK=0/RS=OnSynb5PqLHcGlxDbsJRgEqfmuM-)
See:
typedef struct _HANDLEENTRY {
PVOID phead;
PVOID pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY, *PHANDLEENTRY;
typedef struct _SERVERINFO {
WORD wRIPFlags;
WORD wSRVIFlags;
WORD wRIPPID;
WORD wRIPError;
ULONG cHandleEntries;
} SERVERINFO, *PSERVERINFO;
typedef struct _SHAREDINFO {
PSERVERINFO psi;
PHANDLEENTRY aheList;
ULONG HeEntrySize;
} SHAREDINFO, *PSHAREDINFO;
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[229];
PVOID Reserved3[59];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _TEB
{
NT_TIB Tib;
PVOID EnvironmentPointer;
CLIENT_ID Cid;
PVOID ActiveRpcInfo;
PVOID ThreadLocalStoragePointer;
PPEB Peb;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG Win32ClientInfo[0x1F];
PVOID WOW32Reserved;
ULONG CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID SystemReserved1[0x36];
PVOID Spare1;
ULONG ExceptionCode;
ULONG SpareBytes1[0x28];
PVOID SystemReserved2[0xA];
ULONG GdiRgn;
ULONG GdiPen;
ULONG GdiBrush;
CLIENT_ID RealClientId;
PVOID GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocaleInfo;
PVOID UserReserved[5];
PVOID GlDispatchTable[0x118];
ULONG GlReserved1[0x1A];
PVOID GlReserved2;
PVOID GlSectionInfo;
PVOID GlSection;
PVOID GlTable;
PVOID GlCurrentRC;
PVOID GlContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[0x105];
PVOID DeallocationStack;
PVOID TlsSlots[0x40];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[0x2];
ULONG HardErrorDisabled;
PVOID Instrumentation[0x10];
PVOID WinSockData;
ULONG GdiBatchCount;
ULONG Spare2;
ULONG Spare3;
ULONG Spare4;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
PVOID StackCommit;
PVOID StackCommitMax;
PVOID StackReserved;
} TEB, *PTEB;
int GetgSharedInfo()
{
PSHAREDINFO gSharedInfo=NULL;
HMODULE huser32=NULL;
PHANDLEENTRY aheList=NULL;
ULONG_PTR pfnUserRegisterWowHandlers=NULL;
ULONG_PTR k;
huser32=LoadLibrary(L"user32.dll");
if (huser32 == NULL)
{
printf("LoadLibrary faild\n");
return 0;
}
pfnUserRegisterWowHandlers = (ULONG_PTR)GetProcAddress(huser32, "UserRegisterWowHandlers");
if(pfnUserRegisterWowHandlers ==NULL)
{
printf("UserRegisterWowHandlers faild\n");
return 0;
}
gSharedInfo = (PSHAREDINFO)GetProcAddress(huser32, "gSharedInfo");
if( gSharedInfo != NULL )
{
printf("gSharedInfo=0x%x\n",gSharedInfo);
}
aheList = gSharedInfo->aheList;
k = gSharedInfo->psi->cHandleEntries;
PTEB pTeb = (PTEB)NtCurrentTeb();
UINT_PTR offset = pTeb->Win32ClientInfo[7];
for(ULONG i = 0; i < k; ++i)
{
HANDLEENTRY* pHandle = &aheList[i];
if(pHandle->bType != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)((PVOID*)pHandle->phead - offset);
if(HookInfo)
{
printf("Found hook at %p\n", HookInfo);
printf("Handle of hook is: %.8X",(HOOK*)HookInfo->Handle);
}
}
return 1;
}
(http://image.prntscr.com/image/b789191494b24ee1b8244a8dd3290518.png)
OK, see this is why you don't use undocumented stuff, because it changes. On 7x64 the proper offset is in slot 5 of Win32ClientInfo not 7. Also, that teb struct is 32-bit.
// other structs as necessary
typedef struct _HOOK
{
HANDLE Handle;
ULONG LockObj;
PVOID ThreadInfo;
PVOID Desktop1;
PVOID Self;
PVOID NextHook;
LONG HookType; // WH_ type
PVOID FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
ULONG bitField;
} HOOK;
typedef struct _NeededTEB
{
BYTE unneeded[0x800];
UINT_PTR Win32ClientInfo[0x3e];
} NeededTEB;
#ifndef _WIN64
#error "64-bit only"
#endif
void EnumHooks()
{
HMODULE hMod = GetModuleHandleW(L"user32.dll");
SHARED_INFO* pSharedInf = (SHARED_INFO*)GetProcAddress(hMod, "gSharedInfo");
if(!pSharedInfo) {printf("This isn't Win7 or above\n"); return;}
SIZE_T numHandles = pSharedInf->ServerInfo->numHandles;
NeededTEB* pTeb = (NeededTEB*)NtCurrentTeb();
UINT_PTR offset = pTeb->Win32ClientInfo[5];
printf("EnumHooks found %Iu handles, teb offset = %Ix\n", numHandles, offset);
for(SIZE_T i = 0; i < numHandles; ++i)
{
HANDLE_ENTRY* pEntry = &pSharedInf->HandleEntryList[i];
if(pEntry->Type == TYPE_HOOK)
{
HOOK* pHook = (HOOK*)(((UINT_PTR)pEntry->Head) - offset);
printf("Handle %Iu - Found hook at %p\nHandle = %p - Type = %d\n", i, pHook, pHook->Handle, pHook->HookType);
}
}
}
EnumHooks found 4778 handles, teb offset = fffff900c0010000
Handle 127 - Found hook at 00000000007F2AA0
Handle = 00000000000A007F - Type = -1
Handle 153 - Found hook at 0000000000801D50
Handle = 0000000000050099 - Type = 5
Handle 493 - Found hook at 0000000000813C50
Handle = 00000000005E01ED - Type = 2
Handle 635 - Found hook at 00000000009366D0
Handle = 000000000731027B - Type = 3
etc
Quote from: adeyblue on March 22, 2017, 06:55:19 AM
OK, see this is why you don't use undocumented stuff, because it changes. On 7x64 the proper offset is in slot 5 of Win32ClientInfo not 7. Also, that teb struct is 32-bit.
// other structs as necessary
typedef struct _HOOK
{
HANDLE Handle;
ULONG LockObj;
PVOID ThreadInfo;
PVOID Desktop1;
PVOID Self;
PVOID NextHook;
LONG HookType; // WH_ type
PVOID FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
ULONG bitField;
} HOOK;
typedef struct _NeededTEB
{
BYTE unneeded[0x800];
UINT_PTR Win32ClientInfo[0x3e];
} NeededTEB;
#ifndef _WIN64
#error "64-bit only"
#endif
void EnumHooks()
{
HMODULE hMod = GetModuleHandleW(L"user32.dll");
SHARED_INFO* pSharedInf = (SHARED_INFO*)GetProcAddress(hMod, "gSharedInfo");
if(!pSharedInfo) {printf("This isn't Win7 or above\n"); return;}
SIZE_T numHandles = pSharedInf->ServerInfo->numHandles;
NeededTEB* pTeb = (NeededTEB*)NtCurrentTeb();
UINT_PTR offset = pTeb->Win32ClientInfo[5];
printf("EnumHooks found %Iu handles, teb offset = %Ix\n", numHandles, offset);
for(SIZE_T i = 0; i < numHandles; ++i)
{
HANDLE_ENTRY* pEntry = &pSharedInf->HandleEntryList[i];
if(pEntry->Type == TYPE_HOOK)
{
HOOK* pHook = (HOOK*)(((UINT_PTR)pEntry->Head) - offset);
printf("Handle %Iu - Found hook at %p\nHandle = %p - Type = %d\n", i, pHook, pHook->Handle, pHook->HookType);
}
}
}
EnumHooks found 4778 handles, teb offset = fffff900c0010000
Handle 127 - Found hook at 00000000007F2AA0
Handle = 00000000000A007F - Type = -1
Handle 153 - Found hook at 0000000000801D50
Handle = 0000000000050099 - Type = 5
Handle 493 - Found hook at 0000000000813C50
Handle = 00000000005E01ED - Type = 2
Handle 635 - Found hook at 00000000009366D0
Handle = 000000000731027B - Type = 3
etc
@AdeyBlue,
thank very much, now your code works (building as x64 app).
You have a 32 bit version of this code?
the first code that i posted works fine only until Windows 8 32 bit :(
@AdeyBlue,
thank very much, now your code works (building as x64 app).
You have a 32 bit version of this code?
the first code that i posted works fine only until Windows 8 32 bit :(
@TWell,
i tested your code and also works :t (except the 32-bit part).
@TWell,
you code is failing on 32 bit version :(. See below:
(http://image.prntscr.com/image/a9df523edbae49feaceb76a7f906b097.png)
My GetgSharedInfo() function is like this:
SHAREDINFO* GetgSharedInfo(){
SHAREDINFO* gSharedInfo=NULL;
HMODULE huser32=NULL;
huser32=LoadLibrary(L"user32.dll");
if (huser32 == NULL)
{
printf("LoadLibrary faild\n");
return 0;
}
gSharedInfo = (SHAREDINFO*)GetProcAddress(huser32, "gSharedInfo");
if( gSharedInfo != NULL )
{
return gSharedInfo;
}
return NULL;
}
I don't have a Windows 7 32-bit, so i can't test it.
Under Windows x64 or WindowsXP it won't work.
Quote from: TWell on March 24, 2017, 03:24:11 AM
I don't have a Windows 7 32-bit, so i can't test it.
Under Windows x64 or WindowsXP it won't work.
This was tested in a
Windows 7 32-bit (phisycal computer and also in a Virtual Machine VmWare).
Thanks for the info.
@TWell,
Some times, *pHandle is empty, generating this error of Access Violation.
How solve?
As that cHandleEntries was wrong, try this insteadULONG cHandleEntries = pSharedInfo->psi->cHandleEntries;
another wayULONG cHandleEntries = *(ULONG*)(*((BYTE**)pSharedInfo)+8);
in test program#ifdef _WIN64
if (*(ULONG*)(((BYTE*)gSharedInfo)+16) == 24) { // win64 Win 7 ->
EnumHandles(gSharedInfo);
}
#else
if (*(ULONG*)(((BYTE*)gSharedInfo)+8) == 18) { // win32 Win 7 ->
EnumHandles(gSharedInfo);
} else if (*(ULONG*)(((BYTE*)gSharedInfo)+16) == 24) { // win32 WOW64 Win 7 ->
EnumHandles3264(gSharedInfo);
}
#endif
@TWell,
I still have received Access Violation when tested in Windows 7 32 bit after last changes, but now in other place on code see:
(http://image.prntscr.com/image/08cfe963e74a427baeb76f5bc64c3d35.png)
Here is complete code:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
int printf(const char * restrictformat, ...);
#define TYPE_HOOK 5
typedef struct _HANDLEENTRY64 {
ULONGLONG pHead;
ULONGLONG pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY64, *PHANDLEENTRY64;
typedef struct _SHAREDINFO64 {
ULONGLONG psi;
ULONGLONG aheList;
ULONG HeEntrySize;
ULONGLONG pDispInfo;
ULONG_PTR ulSharedDelta;
ULONG_PTR awmControl;
ULONG_PTR DefWindowMsgs;
ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO64, *PSHAREDINFO64;
typedef struct _HOOK_
{
ULONGLONG Handle;
ULONG LockObj;
ULONGLONG ThreadInfo;
ULONGLONG Desktop1;
ULONGLONG Self;
ULONGLONG NextHook;
LONG HookType;
ULONGLONG FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
} HOOK_, *PHOOK, **PPHOOK;
void EnumHandles3264(SHAREDINFO64 *pSharedInfo64)
{
struct _TEB* pTeb = NtCurrentTeb();
ULONGLONG offset = *(ULONGLONG*)(((BYTE*)pTeb) - 0x2000 + 0x800 + 0x28); // pTeb->Win32ClientInfo.ulClientDelta
ULONG cHandleEntries = *((ULONG *)((ULONG)pSharedInfo64->psi + 8));
HANDLEENTRY64 *Handle = (HANDLEENTRY64*)pSharedInfo64->aheList;
for (ULONG i = 0; i < cHandleEntries; ++i)
{
HANDLEENTRY64* pHandle = Handle++;
if (pHandle->bType != TYPE_HOOK) continue;
HOOK_* HookInfo = (HOOK_*)((UINT_PTR)pHandle->pHead - offset);
if (HookInfo)
{
printf("Found hook at %p", HookInfo);
printf(" Handle: %08llX %2d %d\n", HookInfo->Handle, HookInfo->HookType, HookInfo->Flags);
}
}
}
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
typedef struct _HOOK
{
HANDLE Handle;
ULONG LockObj;
PVOID ThreadInfo;
PVOID Desktop1;
PVOID Self;
PVOID NextHook;
LONG HookType;
PVOID FunctionAddress;
ULONG Flags;
ULONG ModuleHandle;
PVOID Hooked;
PVOID Desktop2;
ULONG bitField;
} HOOK, *PHHOOK, **PPHHOOK;
typedef struct _HANDLEENTRY {
PVOID pHead;
PVOID pOwner;
BYTE bType;
BYTE bFlags;
WORD wUniq;
} HANDLEENTRY, *PHANDLEENTRY;
typedef struct _SERVERINFO {
WORD wRIPFlags;
WORD wSRVIFlags;
WORD wRIPPID;
WORD wRIPError;
ULONG cHandleEntries;
// incomplete
} SERVERINFO, *PSERVERINFO;
typedef struct _SHAREDINFO {
PSERVERINFO psi;
PHANDLEENTRY aheList;
ULONG HeEntrySize;
ULONG_PTR pDispInfo;
ULONG_PTR ulSharedDelta;
ULONG_PTR awmControl;
ULONG_PTR DefWindowMsgs;
ULONG_PTR DefWindowSpecMsgs;
} SHAREDINFO, *PSHAREDINFO;
void EnumHandles(SHAREDINFO *pSharedInfo)
{
struct _TEB* pTeb = NtCurrentTeb();
#ifdef _WIN64
ULONGLONG offset = *(ULONGLONG*)(((BYTE*)pTeb) + 0x800 + 0x28); // pTeb->Win32ClientInfo.ulClientDelta
#else
ULONG offset = *(ULONG*)(((BYTE*)pTeb) + 0x6CC + 0x1C); // pTeb->Win32ClientInfo.ulClientDelta
#endif
ULONG cHandleEntries = pSharedInfo->psi->cHandleEntries;
HANDLEENTRY *Handle = (HANDLEENTRY*)pSharedInfo->aheList;
for (ULONG i = 0; i < cHandleEntries; ++i)
{
HANDLEENTRY* pHandle = Handle++;
if (pHandle->bType != TYPE_HOOK) continue;
HOOK* HookInfo = (HOOK*)((UINT_PTR)pHandle->pHead - offset);
if (HookInfo)
{
printf("Found hook at %p", HookInfo);
printf(" Handle: %08llX %2d %d\n", HookInfo->Handle, HookInfo->HookType, HookInfo->Flags);
}
}
}
PVOID GetgSharedInfo() {
PVOID gSharedInfo = NULL;
HMODULE huser32 = NULL;
huser32 = LoadLibrary(L"user32.dll");
if (huser32 == NULL)
{
printf("LoadLibrary faild\n");
return gSharedInfo;
}
gSharedInfo = GetProcAddress(huser32, "gSharedInfo");
if (gSharedInfo != NULL)
{
return gSharedInfo;
}
return gSharedInfo;
}
int main()
{
#ifdef _WIN64
if (*(ULONG*)(((BYTE*)gSharedInfo) + 16) == 24) { // win64 Win 7 ->
EnumHandles(((SHAREDINFO*)GetgSharedInfo()));
}
#else
//if (*(ULONG*)(((BYTE*)GetgSharedInfo()) + 8) == 18) { // win32 Win 7 ->
EnumHandles(((SHAREDINFO*)GetgSharedInfo()));
//}
//else if (*(ULONG*)(((BYTE*)GetgSharedInfo()) + 16) == 24) { // win32 WOW64 Win 7 ->
//EnumHandles3264((SHAREDINFO64*)GetgSharedInfo());
//}
#endif
system("pause");
return 0;
}
Please, give us output of this program from Windows 7 32-bit.#define WIN32_LEAN_AND_MEAN
#include <windows.h>
int printf(const char * restrict format, ...);
typedef struct _SERVERINFO {
#ifdef _WIN64
DWORD64 dwSRVIFlags;
#else
DWORD dwSRVIFlags;
#endif
ULONG cHandleEntries;
// incomplete
} SERVERINFO, *PSERVERINFO;
typedef struct _SHAREDINFO {
// PVOID psi;
PSERVERINFO psi;
PVOID aheList;
ULONG HeEntrySize;
// incomplete
} SHAREDINFO, *PSHAREDINFO;
int main(void)
{
SHAREDINFO *pSharedInfo = (SHAREDINFO *)GetProcAddress(LoadLibraryA("user32"), "gSharedInfo");
printf("\nSharedInfo %ph\n", pSharedInfo);
printf("SharedInfo->psi->cHandleEntries %u\n", pSharedInfo->psi->cHandleEntries);
printf("SharedInfo->aheList %ph\n", pSharedInfo->aheList);
printf("SharedInfo->HeEntrySize %Xh\n", pSharedInfo->HeEntrySize);
// more test
ULONG ul;
#ifndef _WIN64
if (*(ULONG*)(((BYTE*)pSharedInfo)+8) == 18) {
ul = *(ULONG*)(((BYTE*)pSharedInfo->psi)+4); // OK
printf("cHandleEntries %u\n", ul);
ul = *(ULONG*)(*((BYTE**)pSharedInfo)+4); // another way
printf("cHandleEntries %u\n", ul);
printf("aheList %ph\n", *(ULONG*)(((BYTE*)pSharedInfo)+4));
} else
#endif
if (*(ULONG*)(((BYTE*)pSharedInfo)+16) == 24) { // win64 / win32 WOW64 Win 7 ->
ul = *(ULONG*)(((BYTE*)pSharedInfo->psi)+8); // OK
printf("cHandleEntries %u\n", ul);
ul = *(ULONG*)(*((BYTE**)pSharedInfo)+8); // another way
printf("cHandleEntries %u\n", ul);
printf("aheList %ph\n", *(ULONG*)(((BYTE*)pSharedInfo)+8));
}
return 0;
}
EDIT: fix 32-bit test
Win7-64:
SharedInfo 76bb04e0h
SharedInfo->psi->cHandleEntries 2389
gSharedInfo->aheList 00000000h
SharedInfo->HeEntrySize 4E0000h
cHandleEntries 2389
cHandleEntries 2389
Windows 7 32-bit
(http://image.prntscr.com/image/ede6a222ebb348a4ab53d2dc46037f80.png)
Windows 7 64-bit
(http://image.prntscr.com/image/3a33060c233449b0a70702c0067e77ef.png)
@TWeel,
i already solved this trouble ;).
HANDLEENTRY
SERVERINFO
SHAREDINFO
are wrongs for Windows 7 32-bit.
These structs of link below that are correct, see WIN32K.SYS OBJECT HANDLE ADDRESSES on following link:
http://www.securitynewspaper.com/2017/02/22/revisiting-windows-security-hardening-kernel-address-protection/ (http://www.securitynewspaper.com/2017/02/22/revisiting-windows-security-hardening-kernel-address-protection/)