Closed pokevas closed 4 years ago
Hmm, did you launch the 64 bit app with runshc32.exe? It is a version for 32 bit binaries only.Try launching it with runshc64.exe rather than runshc32.exe and let me know if it helps. In the meanwhile I will check your code...
My mistake is in the description. Of course, I tested the x64 shellcode with runshc64.exe And I thought maybe a problem with runshc64.exe, and tried other methods (injection into the process, for example). But the result is negative. I will attach compiled versions in the archive just in case (something can help): test_x86.exe - compiled .exe (working) test_x86_shellcode.bin - compiled shellcode (working) test_x64.exe - compiled .exe (working) test_x64_shellcode.bin - compiled shellcode (NOT working) attach_files.zip
Ok, thank you for the clarification. Sometimes users commit such mistakes, so I just wanted to start by making sure it is not the case. I will examine your materials and check what could be the cause.
I compiled your code as multi-threaded (flag /MT
) and it works fine. Possibly the compilation options were the problem. Check it out:
test_case1_64.zip
You example working. Maybe differences in the compiler options? Could you attach the sln of your project, I will try on it. I attach my, can you see? Maybe something is wrong. I also compile in MT mode. test_project.zip
I generated my sln with the help of CMake, using this CMakeLists.txt
:
cmake_minimum_required (VERSION 2.8)
project (test_case1)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set (srcs
main.cpp
)
set (hdrs
)
add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs})
And the main.cpp
is just your code (with the main function added). Summing up, it looks like this:
main.cpp
#include <Windows.h>
#include <winternl.h>
#include <iostream>
#define ROTR32(value, shift) (((DWORD) value >> (BYTE) shift) | ((DWORD) value << (32 - (BYTE) shift)))
typedef struct _MY_PEB_LDR_DATA {
ULONG Length;
BOOL Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} MY_PEB_LDR_DATA, *PMY_PEB_LDR_DATA;
typedef struct _MY_LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
} MY_LDR_DATA_TABLE_ENTRY, *PMY_LDR_DATA_TABLE_ENTRY;
typedef HMODULE(WINAPI* FuncLoadLibraryA) (LPCSTR lpFileName);
typedef int(WINAPI* FuncMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
HMODULE GetProcAddressByHash(_In_ DWORD dwModuleFunctionHash)
{
PPEB PebAddress;
PMY_PEB_LDR_DATA pLdr;
PMY_LDR_DATA_TABLE_ENTRY pDataTableEntry;
PVOID pModuleBase;
PIMAGE_NT_HEADERS pNTHeader;
DWORD dwExportDirRVA;
PIMAGE_EXPORT_DIRECTORY pExportDir;
PLIST_ENTRY pNextModule;
DWORD dwNumFunctions;
USHORT usOrdinalTableIndex;
PDWORD pdwFunctionNameBase;
PCSTR pFunctionName;
UNICODE_STRING BaseDllName;
DWORD dwModuleHash;
DWORD dwFunctionHash;
PCSTR pTempChar;
DWORD i;
#if defined(_WIN64)
PebAddress = (PPEB)__readgsqword(0x60);
#elif defined(_M_ARM)
// I can assure you that this is not a mistake. The C compiler improperly emits the proper opcodes
// necessary to get the PEB.Ldr address
PebAddress = (PPEB)((ULONG_PTR)_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0);
__emit(0x00006B1B);
#else
PebAddress = (PPEB)__readfsdword(0x30);
#endif
pLdr = (PMY_PEB_LDR_DATA)PebAddress->Ldr;
pNextModule = pLdr->InLoadOrderModuleList.Flink;
pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY)pNextModule;
while (pDataTableEntry->DllBase != NULL)
{
dwModuleHash = 0;
pModuleBase = pDataTableEntry->DllBase;
BaseDllName = pDataTableEntry->BaseDllName;
pNTHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)pModuleBase + ((PIMAGE_DOS_HEADER)pModuleBase)->e_lfanew);
dwExportDirRVA = pNTHeader->OptionalHeader.DataDirectory[0].VirtualAddress;
// Get the next loaded module entry
pDataTableEntry = (PMY_LDR_DATA_TABLE_ENTRY)pDataTableEntry->InLoadOrderLinks.Flink;
// If the current module does not export any functions, move on to the next module.
if (dwExportDirRVA == 0)
{
continue;
}
// Calculate the module hash
for (i = 0; i < BaseDllName.MaximumLength; i++)
{
pTempChar = ((PCSTR)BaseDllName.Buffer + i);
dwModuleHash = ROTR32(dwModuleHash, 13);
if (*pTempChar >= 0x61)
{
dwModuleHash += *pTempChar - 0x20;
}
else
{
dwModuleHash += *pTempChar;
}
}
pExportDir = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)pModuleBase + dwExportDirRVA);
dwNumFunctions = pExportDir->NumberOfNames;
pdwFunctionNameBase = (PDWORD)((PCHAR)pModuleBase + pExportDir->AddressOfNames);
for (i = 0; i < dwNumFunctions; i++)
{
dwFunctionHash = 0;
pFunctionName = (PCSTR)(*pdwFunctionNameBase + (ULONG_PTR)pModuleBase);
pdwFunctionNameBase++;
pTempChar = pFunctionName;
do
{
dwFunctionHash = ROTR32(dwFunctionHash, 13);
dwFunctionHash += *pTempChar;
pTempChar++;
} while (*(pTempChar - 1) != 0);
dwFunctionHash += dwModuleHash;
if (dwFunctionHash == dwModuleFunctionHash)
{
usOrdinalTableIndex = *(PUSHORT)(((ULONG_PTR)pModuleBase + pExportDir->AddressOfNameOrdinals) + (2 * i));
return (HMODULE)((ULONG_PTR)pModuleBase + *(PDWORD)(((ULONG_PTR)pModuleBase + pExportDir->AddressOfFunctions) + (4 * usOrdinalTableIndex)));
}
}
}
// All modules have been exhausted and the function was not found.
return NULL;
}
// this string need to add .reloc table to x64 .exe file
const char* data = "reloc_fix";
VOID CodeRun(VOID)
{
char module[] = { 'u', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
FuncLoadLibraryA MyLoadLibraryA = (FuncLoadLibraryA)GetProcAddressByHash(0x0726774C);
MyLoadLibraryA((LPCSTR)module);
FuncMessageBoxA MyMessageBoxA = (FuncMessageBoxA)GetProcAddressByHash(0x07568345);
MyMessageBoxA(0, 0, 0, 0);
}
int main()
{
CodeRun();
return 0;
}
Maybe problem that i use custom entrypoint and /NODEFAULTLIB ?
Possibly... I am gonna check in details how exactly it affects the loading process... I will let you know what I found.
Thanks you. I use simple project, but can't find where problem.
Thanks to your testcase I found some bugs in the stub, and I fixed them. It should work now. Please let me know if everything is fine.
You can download the latest build from the build server: x64bit build
Now all okey. Thanks you!
Hello I tried to convert the PE file without imports (base-independent file) If the file is built in x86 mode, then no problem, it is launched through runshc32.exe But if x64, then it fails and crashes. I don’t understand what’s the matter. This seems to be a bug. Source code of .exe file (entrypoint - CodeRun function):