Visual Studio C++: inline assembly to C++

Started by flashcoder, March 20, 2017, 11:06:06 AM

Previous topic - Next topic

flashcoder

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


LordAdef

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

flashcoder

@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.

LordAdef

#3
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

flashcoder

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?

adeyblue

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);
}
}
}

flashcoder

#6
@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);
}
}
}



TWell

It works only in native environment?
In WOW64 PHANDLEENTRY is 0 and HeEntrySize is trash? It should be sizeof(HANDLEENTRY)?

flashcoder

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.






TWell

#9
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);
}
}
}

flashcoder

@TWell,

i have a new code ( based in this link:  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-

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;
}



adeyblue

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

flashcoder

#12
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  :(


flashcoder

#13
@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  :(

flashcoder

#14
@TWell,

i tested your code and also works :t (except the 32-bit part).