Files
LeechCore/leechcore/util.c
2026-01-28 23:22:54 +01:00

214 lines
6.1 KiB
C

// util.c : implementation of various utility functions.
//
// (c) Ulf Frisk, 2018-2026
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "util.h"
#include "charutil.h"
/*
* Retrieve the operating system path of the directory which is containing this:
* .dll/.so file.
* -- uszPath
*/
VOID Util_GetPathLib(_Out_writes_(MAX_PATH) PCHAR uszPath)
{
SIZE_T i;
ZeroMemory(uszPath, MAX_PATH);
#ifdef _WIN32
HMODULE hModuleVmm = 0;
WCHAR wszPath[MAX_PATH] = { 0 };
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)Util_GetPathLib, &hModuleVmm);
GetModuleFileNameW(hModuleVmm, wszPath, MAX_PATH - 4);
CharUtil_WtoU(wszPath, -1, (PBYTE)uszPath, MAX_PATH, NULL, NULL, CHARUTIL_FLAG_STR_BUFONLY | CHARUTIL_FLAG_TRUNCATE);
#endif /* _WIN32 */
#if defined(LINUX) || defined(MACOS)
Dl_info Info = { 0 };
if(!dladdr((void *)Util_GetPathLib, &Info) || !Info.dli_fname) {
GetModuleFileNameA(NULL, uszPath, MAX_PATH - 4);
} else {
strncpy(uszPath, Info.dli_fname, MAX_PATH - 1);
}
#endif /* LINUX || MACOS */
if(uszPath[0] == '\0') { return; }
for(i = strlen(uszPath) - 1; i > 0; i--) {
if(uszPath[i] == '/' || uszPath[i] == '\\') {
uszPath[i + 1] = '\0';
return;
}
}
}
/*
* Try retrieve a numerical value from sz. If sz starts with '0x' it will be
* interpreted as hex (base 16), otherwise decimal (base 10).
* -- sz
* -- return
*/
QWORD Util_GetNumericA(_In_ LPSTR sz)
{
BOOL fhex = sz[0] && sz[1] && (sz[0] == '0') && ((sz[1] == 'x') || (sz[1] == 'X'));
return strtoull(sz, NULL, fhex ? 16 : 10);
}
//-----------------------------------------------------------------------------
#define Util_2HexChar(x) (((((x) & 0xf) <= 9) ? '0' : ('a' - 10)) + ((x) & 0xf))
#define UTIL_PRINTASCII \
"................................ !\"#$%&'()*+,-./0123456789:;<=>?" \
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ " \
"................................................................" \
"................................................................" \
BOOL Util_FillHexAscii(_In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset, _Inout_opt_ LPSTR sz, _Inout_ PDWORD pcsz)
{
DWORD i, j, o = 0, iMod, cRows;
// checks
if((cbInitialOffset > cb) || (cbInitialOffset > 0x1000) || (cbInitialOffset & 0xf)) { return FALSE; }
cRows = (cb + 0xf) >> 4;
if(!sz) {
*pcsz = 1 + cRows * 76;
return TRUE;
}
if(!pb || (*pcsz <= cRows * 76)) { return FALSE; }
// fill buffer with bytes
for(i = cbInitialOffset; i < cb + ((cb % 16) ? (16 - cb % 16) : 0); i++)
{
// address
if(0 == i % 16) {
iMod = i % 0x10000;
sz[o++] = Util_2HexChar(iMod >> 12);
sz[o++] = Util_2HexChar(iMod >> 8);
sz[o++] = Util_2HexChar(iMod >> 4);
sz[o++] = Util_2HexChar(iMod);
sz[o++] = ' ';
sz[o++] = ' ';
sz[o++] = ' ';
sz[o++] = ' ';
} else if(0 == i % 8) {
sz[o++] = ' ';
}
// hex
if(i < cb) {
sz[o++] = Util_2HexChar(pb[i] >> 4);
sz[o++] = Util_2HexChar(pb[i]);
sz[o++] = ' ';
} else {
sz[o++] = ' ';
sz[o++] = ' ';
sz[o++] = ' ';
}
// ascii
if(15 == i % 16) {
sz[o++] = ' ';
sz[o++] = ' ';
for(j = i - 15; j <= i; j++) {
if(j >= cb) {
sz[o++] = ' ';
} else {
sz[o++] = UTIL_PRINTASCII[pb[j]];
}
}
sz[o++] = '\n';
}
}
sz[o] = 0;
*pcsz = o;
return TRUE;
}
VOID Util_PrintHexAscii(_In_opt_ PLC_CONTEXT ctxLC, _In_ PBYTE pb, _In_ DWORD cb, _In_ DWORD cbInitialOffset)
{
DWORD szMax = 0;
LPSTR sz;
if(cb > 0x10000) {
if(ctxLC) {
lcprintf(ctxLC, "Large output. Only displaying first 65kB.\n");
} else {
printf("Large output. Only displaying first 65kB.\n");
}
cb = 0x10000 - cbInitialOffset;
}
Util_FillHexAscii(pb, cb, cbInitialOffset, NULL, &szMax);
if(!(sz = LocalAlloc(0, szMax))) { return; }
Util_FillHexAscii(pb, cb, cbInitialOffset, sz, &szMax);
if(ctxLC) {
lcprintf(ctxLC, "%s", sz);
} else {
printf("%s", sz);
}
LocalFree(sz);
}
VOID Util_SplitN(_In_ LPSTR sz, _In_ CHAR chDelimiter, _In_ DWORD cpsz, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Inout_ LPSTR *psz)
{
DWORD i, j;
strcpy_s(_szBuf, MAX_PATH, sz);
psz[0] = _szBuf;
for(i = 1; i < cpsz; i++) {
psz[i] = "";
}
for(i = 0, j = 0; i < MAX_PATH; i++) {
if('\0' == _szBuf[i]) {
return;
}
if(chDelimiter == _szBuf[i]) {
j++;
if(j >= cpsz) {
return;
}
_szBuf[i] = '\0';
psz[j] = _szBuf + i + 1;
}
}
}
VOID Util_Split2(_In_ LPSTR sz, _In_ CHAR chDelimiter, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2)
{
LPSTR psz[2] = { 0 };
Util_SplitN(sz, chDelimiter, 2, _szBuf, psz);
*psz1 = psz[0];
*psz2 = psz[1];
}
VOID Util_Split3(_In_ LPSTR sz, _In_ CHAR chDelimiter, _Out_writes_(MAX_PATH) PCHAR _szBuf, _Out_ LPSTR *psz1, _Out_ LPSTR *psz2, _Out_ LPSTR *psz3)
{
LPSTR psz[3] = { 0 };
Util_SplitN(sz, chDelimiter, 3, _szBuf, psz);
*psz1 = psz[0];
*psz2 = psz[1];
*psz3 = psz[2];
}
VOID Util_GenRandom(_Out_ PBYTE pb, _In_ DWORD cb)
{
DWORD i = 0;
srand((unsigned int)GetTickCount64());
if(cb % 2) {
*(PBYTE)(pb) = (BYTE)rand();
i++;
}
for(; i <= cb - 2; i += 2) {
*(PWORD)(pb + i) = (WORD)rand();
}
}
BOOL Util_IsPlatformBitness64()
{
BOOL fWow64 = TRUE;
if(Util_IsProgramBitness64()) {
return TRUE;
}
IsWow64Process(GetCurrentProcess(), &fWow64);
return fWow64;
}
BOOL Util_IsProgramBitness64()
{
#ifndef _WIN64
return FALSE;
#endif /* _WIN64 */
return TRUE;
}