Skip to content

Instantly share code, notes, and snippets.

@BlackOfWorld
Last active August 17, 2019 20:09
Show Gist options
  • Save BlackOfWorld/0e89a9ba65a6db28eb5aa6b61da44e1b to your computer and use it in GitHub Desktop.
Save BlackOfWorld/0e89a9ba65a6db28eb5aa6b61da44e1b to your computer and use it in GitHub Desktop.
Detects ASI loader by detecting JMP opcodes inside known function that ASI loader hooks & checks sectors that aren't writable by default (xlive.dll)
bool IsASILoaderPresent() // now it can detect xlive, but possibly broken, can't test
{
HMODULE handle = nullptr;
FARPROC pos = 0;
const char* names[16][2] = {
{"d3d9.dll","D3DPERF_BeginEvent"},
{"d3d11.dll","D3D11CoreCreateDevice"},
{"dsound.dll","DirectSoundCaptureCreate"},
{"d3d8.dll","Direct3DCreate8"},
{"ddraw.dll","DirectDrawCreate"},
{"dinput.dll","DirectInputCreateA"},
{"dinput8.dll","DirectInput8Create"},
{"msacm32.dll","acmDriverAddA"},
{"msvfw32.dll","DrawDibBegin"},
{"version.dll", "GetFileVersionInfoA"},
{"wininet.dll","GetProxyDllInfo"},
{"winmm.dll","midiOutReset"},
{"binkw32Hooked.dll",""},
{"vorbisHooked.dll",""},
{"vorbisFile.dll","ov_pcm_total"},
{"binkw32.dll","_BinkOpen@8"}
};
for (int i = 0; i < 16; i++) {
if (handle = GetModuleHandleA(names[i][0])) {
if (handle != INVALID_HANDLE_VALUE && names[i][0] == "") return true;
pos = GetProcAddress(handle, names[i][1]);
#ifdef _WIN64
if ((*(unsigned char*)pos == 0xFF) && (*((unsigned char*)pos + 1) == 0x24)) return true; // uh oh! jump!
#else
if ((*(unsigned char*)pos == 0xFF) && (*((unsigned char*)pos + 1) == 0x25)) return true; // uh oh! jump!
#endif
}
}
if (handle = GetModuleHandleA("xlive.dll"))
{
auto dosHeader = (PIMAGE_DOS_HEADER)handle;
auto imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)handle + dosHeader->e_lfanew);
PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)imageNTHeaders + sizeof(DWORD) + (DWORD)(sizeof(IMAGE_FILE_HEADER)) + (DWORD)imageNTHeaders->FileHeader.SizeOfOptionalHeader);
byte trigger = 0; // trigger, if 2, both .text and .rdata is writable, this only happens with asi loader
for (int i = 0; i < imageNTHeaders->FileHeader.NumberOfSections; i++) {
// since the dll is now in mapped format, we don't want pointer to raw data
if (stricmp((char*)sectionHeader->Name, ".text") || stricmp((char*)sectionHeader->Name, ".rdata"))
{
MEMORY_BASIC_INFORMATION mbi = { 0 };
VirtualQuery((void*)((DWORD)handle + sectionHeader->VirtualAddress), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (mbi.AllocationProtect == (sectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)
trigger++;
}
sectionHeader++;
}
if (trigger >= 2) return true; // both .text and .rdata is writable, it's asi loader!!
}
return false; // no jump
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment