Last active
January 9, 2020 23:44
-
-
Save hasherezade/3ff7e15cfdef6498c74d5f6761567884 to your computer and use it in GitHub Desktop.
Zbot - checksum lookup (v2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <tlhelp32.h> | |
#include <iostream> | |
#include <peconv.h> // include libPeConv header (https://github.com/hasherezade/libpeconv) | |
#include <paramkit.h> // include ParamKit header (https://github.com/hasherezade/paramkit) | |
using namespace paramkit; | |
#define PARAM_CHECKSUM "checks" | |
#define PARAM_CHECKSUM_FUNC "cfunc" | |
#define PARAM_LIB_ID "lib" | |
#define PARAM_LIB_FUNC "lfunc" | |
bool add_dlls(peconv::ExportsMapper &mapper) | |
{ | |
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32 | TH32CS_SNAPMODULE, GetCurrentProcessId()); | |
if (hModuleSnap == INVALID_HANDLE_VALUE) | |
{ | |
return false; | |
} | |
MODULEENTRY32 me32 = { 0 }; | |
me32.dwSize = sizeof(MODULEENTRY32); | |
if (!Module32First(hModuleSnap, &me32)) | |
{ | |
CloseHandle(hModuleSnap); | |
return false; | |
} | |
#ifdef _DEBUG | |
std::cout << me32.szModule << " : " << std::hex << me32.hModule << "\n"; | |
#endif | |
mapper.add_to_lookup(me32.szModule, LoadLibraryA(me32.szModule)); | |
while (Module32Next(hModuleSnap, &me32)) { | |
#ifdef _DEBUG | |
std::cout << me32.szModule << " : " << std::hex << me32.hModule << "\n"; | |
#endif | |
mapper.add_to_lookup(me32.szModule, LoadLibraryA(me32.szModule)); | |
} | |
CloseHandle(hModuleSnap); | |
return true; | |
} | |
class LookupParams : public Params | |
{ | |
public: | |
LookupParams() | |
: Params() | |
{ | |
this->addParam(new IntParam(PARAM_CHECKSUM, true)); | |
this->setInfo(PARAM_CHECKSUM, "Function checksum: hex"); | |
this->addParam(new IntParam(PARAM_CHECKSUM_FUNC, true)); | |
this->setInfo(PARAM_CHECKSUM_FUNC, "RVA of the function calculating the checksum"); | |
this->addParam(new IntParam(PARAM_LIB_ID)); | |
this->setInfo(PARAM_LIB_ID, "Library ID: dec"); | |
this->addParam(new IntParam(PARAM_LIB_FUNC, true)); | |
this->setInfo(PARAM_LIB_FUNC, "RVA of the function calculating the lib ID"); | |
} | |
}; | |
bool params_resolve(LookupParams ¶ms, BYTE *my_pe) | |
{ | |
if (!params.isSet(PARAM_CHECKSUM) | |
&& params.isSet(PARAM_CHECKSUM_FUNC)) | |
{ | |
DWORD func_addr = params.getIntValue(PARAM_CHECKSUM_FUNC); | |
int(*get_checksum)() = (int(*)())(func_addr + (ULONG_PTR)my_pe); | |
params.setIntValue(PARAM_CHECKSUM, get_checksum()); | |
} | |
if (!params.isSet(PARAM_LIB_ID) | |
&& params.isSet(PARAM_LIB_FUNC)) | |
{ | |
DWORD func_addr = params.getIntValue(PARAM_LIB_FUNC); | |
int(*get_checksum)() = (int(*)())(func_addr + (ULONG_PTR)my_pe); | |
params.setIntValue(PARAM_LIB_ID, get_checksum()); | |
} | |
if (!params.isSet(PARAM_LIB_ID) || !params.isSet(PARAM_CHECKSUM)) { | |
return false; | |
} | |
return true; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
LookupParams params; | |
if (argc < 2) { | |
std::cout << "Args: <path to the exe*> <params...>\n" | |
"*required exe: Zbot, md5 = ab756f154d266c8ba19bdfa8bcaf1b73\nparams:\n"; | |
params.info(); | |
return 0; | |
} | |
if (!params.parse(argc, argv)) { | |
params.info(); | |
return 0; | |
} | |
LPCSTR pe_path = argv[1]; | |
// manually load the PE file using libPeConv: | |
size_t v_size = 0; | |
//if the PE is dropped on the disk, you can load it from the file: | |
BYTE* my_pe = peconv::load_pe_executable(pe_path, v_size); | |
if (!my_pe) { | |
return -1; | |
} | |
std::cout << "[+] Loaded!\n"; | |
char(*init_imports_lookup)() = nullptr; | |
init_imports_lookup = (char(*)())(0x1000 + (ULONG_PTR)my_pe); | |
if (!init_imports_lookup()) { | |
std::cout << "[-] Init failed!\n"; | |
return -1; | |
} | |
FARPROC(__cdecl *load_func_by_checksum)(DWORD lib_id, DWORD checksum) = nullptr; | |
load_func_by_checksum = (FARPROC(__cdecl *)(DWORD, DWORD)) (0x151E + (ULONG_PTR)my_pe); | |
if (!params_resolve(params, my_pe)) { | |
std::cout << "Some params are missing!\n"; | |
params.print(); | |
return -3; | |
} | |
DWORD lib_id = params.getIntValue(PARAM_LIB_ID); | |
DWORD checks = params.getIntValue(PARAM_CHECKSUM); | |
std::cout << "LidID: " << std::hex << lib_id << " checksum: " << checks << "\n"; | |
FARPROC proc = load_func_by_checksum(lib_id, checks); | |
if (!proc) { | |
std::cout << "[!] Function not found!\n"; | |
return 1; | |
} | |
peconv::ExportsMapper mapper; | |
add_dlls(mapper); | |
std::cout << "[+] Function retrieved: " << std::hex << proc << "\n"; | |
ULONGLONG proc_addr = (ULONGLONG)proc; | |
const peconv::ExportedFunc *exp = mapper.find_export_by_va(proc_addr); | |
DWORD shift = 0; | |
while (!exp) { | |
shift++; | |
exp = mapper.find_export_by_va(proc_addr - shift); | |
} | |
if (exp) { | |
std::cout << exp->toString() << "\n"; | |
if (shift) { | |
std::cout << "shift: " << std::hex << "0x" << shift << "\n"; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment