Я лучше тебя
-
Автор темы
- #1
Шалом, давно не писал статеек, много проблем и работы навалилось.
Для чего это нужно?
Конечному потребителю кода стоит учесть: это лишь наброски, не претендующие на абсолютно идеальную финальную версию.К всеобщему обозрению, предоставляю концепцию хранения апи (функций чего угодно) за пределами программы.
(в C# это называется динамическая сборка с поздним связыванием)
Для чего это нужно?
- Хранение важного кода за пределами программы. (в отдельной длл)
За пределами программы - это где угодно, в ресурсах, в памяти, на веб-сайте.
- Определение условий, при которых ваша программа получит этот самый важный код остается на ваше усмотрение.
(самый распространенный пример: проверка лицензии) Прописываете в скрипте сайта, чтобы не выдавал сборку с функциями для инжекта и тп, пока нет лицензии, зачастую это используют для схемы: чтобы крякнуть - сначала купи, или ищи того у кого уже есть.
- Вся аллокация может быть записана в контейнер при желании.
То есть, вы можете скачать с вебчасти и выполнить важный код и удалить все его следы из памяти (если захотите с этим возится), и все это на ЛЕТУ.
Library.h:
Код:
#pragma once
#include <windows.h>
#define EXPORT_API __declspec( dllexport )
//тупо экспортируем все в дллке что нам нужно использовать:
extern "C"
{
EXPORT_API int WINAPI getVersion()
{
return 10;
}
};
Код:
#include "Library.h"
BOOL WINAPI DllMain(HMODULE hDll, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
//Чтобы проверить, загрузилось ли все как надо.
MessageBoxA(0, "tested", "texted", 0);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
API.h (для вашей программы)
Код:
#pragma once
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
struct _EXPOTR_FUNC
{
FARPROC Func;
char* Name;
_EXPOTR_FUNC(FARPROC _a, char* _b)
{
Func = _a;
Name = _b;
}
};
vector<_EXPOTR_FUNC*> _query_export_list(HMODULE Mod)
{
vector<_EXPOTR_FUNC*> t3Vector;
ULONG Portable_Executable;
PIMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY;
PULONG RVAPointer;
PUSHORT oTb_RVA;
PULONG dwTbRVA;
ULONG uReturn = 0;
USHORT tmpINDEX;
char * tmpName;
ULONG Adress;
ULONG size_CNT;
if (Mod)
{
Portable_Executable =
*(ULONG*)((ULONG)Mod + 0x3C) + (ULONG)Mod;
EXPORT_DIRECTORY =
(PIMAGE_EXPORT_DIRECTORY)(*(ULONG*)((ULONG)Portable_Executable + 0x78) + (ULONG)Mod);
RVAPointer =
(ULONG*)(EXPORT_DIRECTORY->AddressOfNames + (ULONG)Mod);
oTb_RVA =
(USHORT*)(EXPORT_DIRECTORY->AddressOfNameOrdinals + (ULONG)Mod);
dwTbRVA =
(ULONG*)(EXPORT_DIRECTORY->AddressOfFunctions + (ULONG)Mod);
if (EXPORT_DIRECTORY->NumberOfNames > EXPORT_DIRECTORY->NumberOfFunctions)
size_CNT = EXPORT_DIRECTORY->NumberOfNames;
else
size_CNT = EXPORT_DIRECTORY->NumberOfFunctions;
for (USHORT i = 0; i < size_CNT; i++)
{
if (i < EXPORT_DIRECTORY->NumberOfFunctions)
{
tmpName = (char*)(RVAPointer[i] + (ULONG)Mod);
tmpINDEX = oTb_RVA[i];
}
else
{
tmpName = 0;
tmpINDEX = i;
}
Adress = dwTbRVA[tmpINDEX] + (ULONG)Mod;
t3Vector.push_back(new _EXPOTR_FUNC((FARPROC)Adress, tmpName));
}
}
return t3Vector;
}
using LoadLibraryFn = HMODULE(WINAPI*)(LPCSTR);
using GetProcAddressFn = FARPROC(WINAPI*)(HMODULE, LPCSTR);
using DllMainFn = BOOL(WINAPI*)(HMODULE, DWORD, PVOID);
typedef struct _INJECT
{
PVOID ImageBase;
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_BASE_RELOCATION BaseRelocation;
PIMAGE_IMPORT_DESCRIPTOR ImportDirectory;
LoadLibraryFn pLoadLibraryA;
GetProcAddressFn pGetProcAddress;
}INJECT, *P_INJECT;
DWORD WINAPI LoadDll(P_INJECT p)
{
P_INJECT m_pInject = (P_INJECT)p;
DWORD i = 0,
Function = 0,
count = 0;
PDWORD ptr = nullptr;
PWORD list = nullptr;
PIMAGE_IMPORT_BY_NAME pIBN = { 0 };
PIMAGE_THUNK_DATA FirstThunk = { 0 };
PIMAGE_THUNK_DATA OrigFirstThunk = { 0 };
DllMainFn EntryPoint = nullptr;
PIMAGE_BASE_RELOCATION pIBR = m_pInject->BaseRelocation;
DWORD delta = (DWORD)((LPBYTE)m_pInject->ImageBase - m_pInject->NtHeaders->OptionalHeader.ImageBase);
while (pIBR->VirtualAddress)
{
if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))
{
count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
list = (PWORD)(pIBR + 1);
for (i = 0; i<count; i++)
{
if (list[i])
{
ptr = (PDWORD)((LPBYTE)m_pInject->ImageBase + (pIBR->VirtualAddress + (list[i] & 0xFFF)));
*ptr += delta;
}
}
}
pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR + pIBR->SizeOfBlock);
}
PIMAGE_IMPORT_DESCRIPTOR pIID = m_pInject->ImportDirectory;
HMODULE hModule = NULL;
while (pIID->Characteristics)
{
OrigFirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)m_pInject->ImageBase + pIID->OriginalFirstThunk);
FirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)m_pInject->ImageBase + pIID->FirstThunk);
hModule = m_pInject->pLoadLibraryA((LPCSTR)m_pInject->ImageBase + pIID->Name);
if (!hModule)
return FALSE;
while (OrigFirstThunk->u1.AddressOfData)
{
if (OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
Function = (DWORD)m_pInject->pGetProcAddress(hModule, (LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF));
if (!Function)
return FALSE;
FirstThunk->u1.Function = Function;
}
else
{
pIBN = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)m_pInject->ImageBase + OrigFirstThunk->u1.AddressOfData);
Function = (DWORD)m_pInject->pGetProcAddress(hModule, (LPCSTR)pIBN->Name);
if (!Function)
return FALSE;
FirstThunk->u1.Function = Function;
}
OrigFirstThunk++;
FirstThunk++;
}
pIID++;
}
if (m_pInject->NtHeaders->OptionalHeader.AddressOfEntryPoint)
{
EntryPoint = (DllMainFn)((LPBYTE)m_pInject->ImageBase + m_pInject->NtHeaders->OptionalHeader.AddressOfEntryPoint);
return EntryPoint((HMODULE)m_pInject->ImageBase, DLL_PROCESS_ATTACH, nullptr);
}
return TRUE;
}
BOOL HideLoadLibrary(PVOID pBuffer, P_INJECT & inject)
{
PIMAGE_DOS_HEADER pIDH = { 0 };
PIMAGE_NT_HEADERS pINH = { 0 };
PIMAGE_SECTION_HEADER pISH = { 0 };
pIDH = (PIMAGE_DOS_HEADER)pBuffer;
if (pIDH->e_magic != IMAGE_DOS_SIGNATURE)
{
std::cout << "Error:: Invalid executable image" << std::endl;
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
pINH = (PIMAGE_NT_HEADERS)((LPBYTE)pBuffer + pIDH->e_lfanew);
if (pINH->Signature != IMAGE_NT_SIGNATURE)
{
std::cout << "Error:: Invalid PE header" << std::endl;
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
if (!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
std::cout << "Error:: The image is not DLL" << std::endl;
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
PVOID image = VirtualAlloc(NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!image)
{
std::cout << "Error:: Allocate memory for the DLL::" << GetLastError() << std::endl;
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
if (!memcpy(image, pBuffer, pINH->OptionalHeader.SizeOfHeaders))
{
std::cout << "Error:: Copy headers to process::" << GetLastError() << std::endl;
VirtualFree(image, 0, MEM_RELEASE);
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
pISH = (PIMAGE_SECTION_HEADER)(pINH + 1);
for (DWORD i = 0; i<pINH->FileHeader.NumberOfSections; i++)
{
memcpy((PVOID)((LPBYTE)image + pISH[i].VirtualAddress), (PVOID)((LPBYTE)pBuffer + pISH[i].PointerToRawData), pISH[i].SizeOfRawData);
}
PVOID mem = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!mem)
{
std::cout << "Error:: Allocate memory for the loader code::" << GetLastError() << std::endl;
VirtualFree(image, 0, MEM_RELEASE);
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
INJECT* m_pInject = new INJECT;
//memset(&m_pInject, 0, sizeof(INJECT));
m_pInject->ImageBase = image;
m_pInject->NtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)image + pIDH->e_lfanew);
m_pInject->BaseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
m_pInject->ImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
m_pInject->pLoadLibraryA = LoadLibraryA;
m_pInject->pGetProcAddress = GetProcAddress;
if (!LoadDll(m_pInject))
{
std::cout << "Error:: Unable to execute loader code::" << GetLastError() << std::endl;
VirtualFree(mem, 0, MEM_RELEASE);
VirtualFree(image, 0, MEM_RELEASE);
VirtualFree(pBuffer, 0, MEM_RELEASE);
return FALSE;
}
VirtualFree( mem, 0, MEM_RELEASE);
if (pINH->OptionalHeader.AddressOfEntryPoint)
{
printf_s("DLL entry point: %#x\n", (PVOID)((LPBYTE)image + pINH->OptionalHeader.AddressOfEntryPoint));
}
VirtualFree(pBuffer, 0, MEM_RELEASE);
std::cout << "DLL injected!" << std::endl;
inject = m_pInject;
return TRUE;
Код:
#include "API.h"
//я догружал длл из шелкода, вы можете откуда угодно
#include "code_file.h"
int main()
{
P_INJECT inject;
//rawData - мой мосив байт из которого я грузил длл
//вы можете получить его прямо с сайта, или с ресурсов, или откуда хотите.
if (HideLoadLibrary((PVOID)rawData, inject))
{
//Прототип нашего експорта:
using _getVersion = int(WINAPI*)();
std::cin.get();
//извлекаем из нашей длл каталог наших експортов:
vector<_EXPOTR_FUNC*> exports = _query_export_list((HMODULE)inject->ImageBase);
//выводим для проверки
for (_EXPOTR_FUNC* func : exports)
{
printf("Name: %s, Address: 0x%X\n", func->Name, func->Func);
}
//обращаемся к функции по адресу
int version = reinterpret_cast<_getVersion>(exports[0]->Func)();
//выводим результат выполнения:
printf("Version: %d", version);
}
std::cin.get();
return 0;
}