Saturday, November 19, 2016

SHGetKnownFolderPath: why is it linked with two jumps?

I noticed a weird behaviour when trying to detour SHGetKnownFolderPath, and investigaed a bit. So I worte a tiny program, and then loaded it in IDA.
The program:

#include "stdafx.h"
#include "windows.h"
#include "FileAPI.h"
#include "Shlobj.h"


int main()
{
    HANDLE hFile = CreateFileA(NULL, 0, 0, NULL, 0, 0, NULL);
    SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, NULL, NULL);
    return 0;
}
Looking in IDA, I see for CreateFileA:
call    ds:__imp__CreateFileA@28 ; CreateFileA(x,x,x,x,x,x,x)
Which takes me to:
.idata:0041B000 ; HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
.idata:0041B000                 extrn __imp__CreateFileA@28:dword ; CODE XREF: _main+2Ep
.idata:0041B000                                         ; DATA XREF: _main+2Er ...
On the other hand, for SHGetKnownFolderPath I see:
call    j__SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
Which redirect to:
; __stdcall SHGetKnownFolderPath(x, x, x, x)
j__SHGetKnownFolderPath@16 proc near
jmp     _SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
j__SHGetKnownFolderPath@16 endp
Which redirect to:
; __stdcall SHGetKnownFolderPath(x, x, x, x)
_SHGetKnownFolderPath@16 proc near
jmp     ds:__imp__SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
_SHGetKnownFolderPath@16 endp
Which redirect to:
.idata:0041B09C ; __declspec(dllimport) __stdcall SHGetKnownFolderPath(x, x, x, x)
.idata:0041B09C                 extrn __imp__SHGetKnownFolderPath@16:dword
.idata:0041B09C                                         ; DATA XREF: SHGetKnownFolderPath(x,x,x,x)r
So SHGetKnownFolderPath have two more jumps then CreateFileA. I did nothing to the project to make it do it. so why?

Update:
Removing Incremental Linking removed j__SHGetKnownFolderPath@16, but left _SHGetKnownFolderPath@16.
From the VS /INCREMENTAL documentation:

  • May contain jump thunks to handle relocation of functions to new addresses

So we have half a solution, and another question: why does this setting effect only this DLL, and not other DLLs? (especially other system DLLs)

Update 2: Solved.
Found out that SHGetKnownFolderPath does not have a __declspec(dllimport) in the definition. Adding it made it be called identical to CreateFileA.
Without it, the compiler created a stub, the linker add a stub of its own for the incremental linking, and only then connected it to the DLL.

Sunday, September 25, 2016

Detecting loaded DLL modules in process

I collected this code from various sources across the net, cleaned and tested it. (VS2015, x86 and x64)
Note that this is for listing the DLL from inside the process, and not from a different one.

It is important to use Loader Lock when dealing with the loader internal structures. It will also make you tread-safe, and make sure that nobody will load another DLL while you are processing the current list.

Alternative to part 1 is the WinAPI call EnumProcessModules.

Part 1: listing currently loaded DLLs



#include <Windows.h>
#include <winnt.h>
#include <winternl.h>


void ListCurrentModules() 
{

  HMODULE ntdll = GetModuleHandleA("ntdll.dll");
  NTSTATUS(NTAPI *LdrLockLoaderLock)(ULONG Flags, ULONG *State, UINT_PTR *Cookie)
    = (NTSTATUS(NTAPI *)(ULONG, ULONG *, UINT_PTR *))GetProcAddress(ntdll, "LdrLockLoaderLock");
  NTSTATUS(NTAPI *LdrUnlockLoaderLock)(ULONG Flags, UINT_PTR Cookie)

    = (NTSTATUS(NTAPI *)(ULONG, UINT_PTR))GetProcAddress(ntdll, "LdrUnlockLoaderLock");

  UINT_PTR ldrCookie;
  LdrLockLoaderLock(0, NULL, &ldrCookie);

#if defined(_M_X64) // x64
  auto pTeb = reinterpret_cast<PTEB>(__readgsqword(reinterpret_cast<UINT_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#elif defined(_M_ARM) // ARM
  auto pTeb = reinterpret_cast<PTEB>(_MoveFromCoprocessor(15, 0, 13, 0, 2)); // CP15_TPIDRURW
#else // x86
  auto pTeb = reinterpret_cast<PTEB>(__readfsdword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif

  auto pPeb = pTeb->ProcessEnvironmentBlock;
  auto pLdrData = pPeb->Ldr;
  auto pModListHdr = &pLdrData->InMemoryOrderModuleList;

  for (auto pModListCurrent = pModListHdr->Flink; pModListCurrent != pModListHdr; pModListCurrent = pModListCurrent->Flink)
  {
    // Get current module in list
    auto pModEntry = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(pModListCurrent);
    HMODULE moduleHandle = (HMODULE)pModEntry->Reserved2[0]; // ModuleBaseAddress
    printf("Module [%S] handle is [%p]\n",
        pModEntry->FullDllName.Buffer, moduleHandle);
  }

  LdrUnlockLoaderLock(0, ldrCookie);
}

Part 2: Getting notifications for DLL loading

I'm using the non official function, LdrRegisterDllNotification.

enum NotificationReasonEnum
{
  LDR_DLL_NOTIFICATION_REASON_LOADED = 1,
  LDR_DLL_NOTIFICATION_REASON_UNLOADED = 2
};

typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
  ULONG Flags;                    //Reserved.
  PCUNICODE_STRING FullDllName;   //The full path name of the DLL module.
  PCUNICODE_STRING BaseDllName;   //The base file name of the DLL module.
  PVOID DllBase;                  //A pointer to the base address for the DLL in memory.
  ULONG SizeOfImage;              //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;

typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
  ULONG Flags;                    //Reserved.
  PCUNICODE_STRING FullDllName;   //The full path name of the DLL module.
  PCUNICODE_STRING BaseDllName;   //The base file name of the DLL module.
  PVOID DllBase;                  //A pointer to the base address for the DLL in memory.
  ULONG SizeOfImage;              //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;

typedef union _LDR_DLL_NOTIFICATION_DATA {
  LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
  LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;

void NTAPI DllNotificationCallback(NotificationReasonEnum eAction, LDR_DLL_NOTIFICATION_DATA *NotificationData, void *Context)
{
  if (eAction == LDR_DLL_NOTIFICATION_REASON_LOADED)
  {
    HANDLE moduleHandle = NotificationData->Loaded.DllBase;
    printf("Module [%S] dynamically loaded handle=%p\n", NotificationData->Loaded.BaseDllName->Buffer, moduleHandle);
  }
}

void RegisterDLLNotifications(PVOID Context) 
{
  HMODULE ntdll = LoadLibraryA("ntdll.dll");
  NTSTATUS(NTAPI *LdrRegisterDllNotification)(ULONG Flags, void *NotificationFunction, PVOID Context, PVOID  *Cookie) 
    = (NTSTATUS(NTAPI *)(ULONG, void *, PVOID, PVOID *))GetProcAddress(ntdll, "LdrRegisterDllNotification");
  void *cookie;
  LdrRegisterDllNotification(0, (void*)DllNotificationCallback, Context, &cookie);
}

Context can be NULL. Surprisingly, cookie is not optional, but you can just discard the value if you don't need to unregister the callback.

Tuesday, August 2, 2016

Direct3D 11.0, 11.1, 11.2 Variants

Looking on the D3D11 DLLs, I see that internally all the variants implemented by the same objects.

But if you create DXGIFactory using CreateDXGIFactory (11.0 variant) the object keeps a flag telling it that it indeed 11.0 variant. I'm not clear what this flag does.
Also, in this case, the object prevent you from doing QueryInterface and upgrading to the 11.1 variant.


Tuesday, July 12, 2016

Thoughts on reversing C++ code

The local globals:
A method in C++ can change a variable that belongs to the object. As it is not a parameter, and not a local variable, then it is kind of global.
But it doesn't have a set location in memory, just an offset from 'this'. so you can't track it unlike a true global.

Calculated calls:
Every virtual call is calculated call. so it is difficult to know in static analysis where this calls goes to.

Virtual call table:
The VTable is saved to the executable as just a list of function pointers.
Listing xref to this list, it will point to the object constructor. And from it all the location that this object was constructed. (but not sub classes, as they have their own VTable)

Highly coupled:
Well, making a change in an object that is inside an inheritance tree is challenging.
Making a change to a method that is shared to other classes is most likely not a good idea.
You can change the class VTable itself, redirecting calls. but unless you want redirect it to null_sub, there is not much that you can do.
I need to think of a way to find which functions are used exclusively by the attacked class.

Wednesday, June 29, 2016

Unity's Invalid DWORD (32-bit) value problem

Apparently, the Unity developers decided that it is good idea to store floating point values in the registry.
The registry does not support floating point, but you know what it does support? Integers. so let's use that!
So they did something like:
double f;
RegSetValueExA ( KeyHandle, ValName, 0, REG_DWORD, &f, sizeof(f) )

It is just that... double is 64-bit type. DWORD is 32-bit type.

Well, Windows doesn't care. For it, the type is just a label on the value, for readability. Internally, all the registry values are binary blobs. 

And that's why I had to implement 64-bit DWORDs. 

Tuesday, June 14, 2016

XInput's hidden functions

Inside X_Input, there are a couple of undocumented functions. You can load them not by name, but by ordinal.
I tried to find as much as I can about them:

DWORD __stdcall __ordinal(100) XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState)
The same as XInputGetState, adding the "Guide" button.
#define XINPUT_GAMEPAD_GUIDE 0x0400

DWORD __stdcall __ordinal(101) XInputWaitForGuideButton(DWORD dwUserIndex, DWORD dwFlags, PVOID pUnKnown)
If dwFlags == 0 - blocking until Guide button is pressed. Otherwise, it is async.
I am not clear on how to get the async option to report.

DWORD __stdcall __ordinal(102) XInputCancelGuideButtonWait(DWORD dwUserIndex)
If XInputWaitForGuideButton was activated in async mode, this will stop it.

DWORD __stdcall __ordinal(103) XInputPowerOffController(DWORD dwUserIndex)
I think that his one is clear.

struct _XINPUT_BASE_BUS_INFORMATION
{
WORD a1;
WORD a2;
DWORD a3;
DWORD Flags; // probably
BYTE a4;
BYTE a5;
BYTE a6;
BYTE reserved;
 }
DWORD __stdcall __ordinal(104) XInputGetBaseBusInformation(DWORD dwUserIndex, XINPUT_BASE_BUS_INFORMATION *pInfo)
Not working on all gamepads. It can refuse and return ERROR_DEVICE_NOT_CONNECTED, even if connected.

struct XINPUT_CAPABILITIES_EX
{
XINPUT_CAPABILITIES Capabilities;
WORD a1;
WORD a2;
WORD a3;
DWORD a4;
};
DWORD __stdcall __ordinal(108) XInputGetCapabilitiesEx(DWORD a1, DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES_EX *pCapabilities)
a1 should probably be 1.

Sunday, June 5, 2016

Monkey business in IMMDeviceEnumerator

winmmbase.dll's function winmmGetMidiInterfaces create a IMMDeviceEnumerator object, and the uses QueryInterface using this UUID:
"3e52272f-3c89-45f8-be26-cb3b91ab42a0"
I couldn't find why and what is this uuid is about.

Wednesday, June 1, 2016

COM objects can be elusive

When proxying a COM object, queryinterface it can be frustrating.
A program can ask for other interface, and then return to the original interface.
If you are not covering all the interfaces that the object support, a program can bypass the proxy this way.

Also, A lot of unexpected interfaces can be created using CoCreateInstance, bypassing their official "create" function.

Thursday, May 19, 2016

ChangeDisplaySettings

Dear game developers,
The next game that will call ChangeDisplaySettings / ChangeDisplaySettingsEx, will have its bits burned one by one.
This is not 1990 anymore.
Thanks.

Wednesday, May 18, 2016

CreateAdditionalSwapChain

Dear game developers,
If your game can use one screen with one picture, there is no reason to CreateAdditionalSwapChain.
Please use the default one.
Thanks.

Tuesday, May 17, 2016

Dual players, one screen

Dear game developers,
If you enable two players locally, there is no reason to render the screen twice in full resolution and then squash them into one.
It kills the GPU, and really have no benefit.
thank you.

Hey Windows - RegisterRawInputDevices

Hey Windows. When the program calls RegisterRawInputDevices, do you think that I don't see you opening a thread and polling constantly?

Sunday, May 15, 2016

Why to simply save my files?

A game probably was written to handle only one user, and then was ported to Steam that supports multiple users.

So what do they do? simple.

Let's copy the save files from Steam to a newly created temp directory, rename them in the process (to remove the profile marker) and use the original function to load it. simple!

Of course, when saving, the reverse process is done.

Should I mention that every time it opens a new directory? and that it fails to delete them afterwards?