Skip to content

Instantly share code, notes, and snippets.

@hasherezade
Last active January 9, 2020 23:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasherezade/3ff7e15cfdef6498c74d5f6761567884 to your computer and use it in GitHub Desktop.
Save hasherezade/3ff7e15cfdef6498c74d5f6761567884 to your computer and use it in GitHub Desktop.
Zbot - checksum lookup (v2)
#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 &params, 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