Files
go_pwner/workspace/bof_basic/PEB_walk.c
T
2026-07-18 21:37:15 +03:00

167 lines
5.1 KiB
C

#include <windows.h>
#include <stdio.h>
#include <string.h>
// Функция для парсинга PEB и поиска WinExec
FARPROC FindWinExec() {
// Получаем PEB через FS регистр
#ifdef _WIN64
PPEB pPEB = (PPEB)__readgsqword(0x60);
#else
PPEB pPEB = (PPEB)__readfsdword(0x30);
#endif
// Получаем LDR (Loader Data)
PPEB_LDR_DATA pLDR = pPEB->Ldr;
// Проходим по списку загруженных модулей
LIST_ENTRY* pModuleList = &pLDR->InMemoryOrderModuleList;
LIST_ENTRY* pEntry = pModuleList->Flink;
// Ищем kernel32.dll
while (pEntry != pModuleList) {
PLDR_DATA_TABLE_ENTRY pModule = CONTAINING_RECORD(pEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
// Проверяем имя модуля
WCHAR* moduleName = pModule->BaseDllName.Buffer;
if (moduleName && wcsstr(moduleName, L"kernel32.dll")) {
HMODULE hKernel32 = (HMODULE)pModule->DllBase;
// Ищем WinExec в kernel32.dll
FARPROC pWinExec = GetProcAddress(hKernel32, "WinExec");
if (pWinExec) {
printf("[+] Found WinExec at: 0x%p\n", pWinExec);
return pWinExec;
}
}
pEntry = pEntry->Flink;
}
return NULL;
}
// Функция для открытия и парсинга .exe файла
void ParseExeFile(const char* filename) {
HANDLE hFile = CreateFileA(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
printf("[-] Failed to open file: %s\n", filename);
return;
}
// Читаем DOS заголовок
IMAGE_DOS_HEADER dosHeader;
DWORD bytesRead;
if (!ReadFile(hFile, &dosHeader, sizeof(dosHeader), &bytesRead, NULL)) {
printf("[-] Failed to read DOS header\n");
CloseHandle(hFile);
return;
}
// Проверяем сигнатуру DOS
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
printf("[-] Invalid DOS signature\n");
CloseHandle(hFile);
return;
}
// Переходим к PE заголовку
SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN);
// Читаем PE сигнатуру
DWORD peSignature;
ReadFile(hFile, &peSignature, sizeof(peSignature), &bytesRead, NULL);
if (peSignature != IMAGE_NT_SIGNATURE) {
printf("[-] Invalid PE signature\n");
CloseHandle(hFile);
return;
}
// Читаем файловый заголовок
IMAGE_FILE_HEADER fileHeader;
ReadFile(hFile, &fileHeader, sizeof(fileHeader), &bytesRead, NULL);
printf("[+] File is a valid PE executable\n");
printf("[+] Number of sections: %d\n", fileHeader.NumberOfSections);
printf("[+] Size of optional header: %d\n", fileHeader.SizeOfOptionalHeader);
// Читаем опциональный заголовок
IMAGE_OPTIONAL_HEADER32 optionalHeader;
ReadFile(hFile, &optionalHeader, sizeof(optionalHeader), &bytesRead, NULL);
printf("[+] Entry point: 0x%X\n", optionalHeader.AddressOfEntryPoint);
printf("[+] Image base: 0x%X\n", optionalHeader.ImageBase);
// Читаем секции
printf("\n[+] Sections:\n");
for (int i = 0; i < fileHeader.NumberOfSections; i++) {
IMAGE_SECTION_HEADER sectionHeader;
ReadFile(hFile, &sectionHeader, sizeof(sectionHeader), &bytesRead, NULL);
printf(" %s - VA: 0x%X, Size: 0x%X\n",
sectionHeader.Name,
sectionHeader.VirtualAddress,
sectionHeader.SizeOfRawData);
}
CloseHandle(hFile);
}
// Функция-победитель (win)
void win(void) {
printf("flag{ret2win_but_its_WINDOWS}\n");
// Находим WinExec через PEB
FARPROC pWinExec = FindWinExec();
if (pWinExec) {
// Запускаем калькулятор через WinExec
typedef void (*WinExec_t)(LPCSTR, UINT);
WinExec_t WinExec_func = (WinExec_t)pWinExec;
WinExec_func("mspaint.exe", SW_SHOW);
printf("[+] paint launched!\n");
}
}
// Уязвимая функция
void vulnerable_function() {
char buf[16];
printf("enter your data:\n");
scanf("%s", buf);
printf("try again\n");
}
int main(int argc, char* argv[]) {
printf("=== Windows Buffer Overflow CTF Challenge ===\n\n");
// Если передан аргумент, парсим .exe файл
if (argc > 1) {
printf("[*] Parsing PE file: %s\n", argv[1]);
ParseExeFile(argv[1]);
printf("\n");
}
// Демонстрируем поиск WinExec через PEB
printf("[*] Finding WinExec via PEB parsing...\n");
FARPROC pWinExec = FindWinExec();
if (pWinExec) {
printf("[+] WinExec found at: 0x%p\n", pWinExec);
}
printf("\n");
// Вызываем уязвимую функцию
vulnerable_function();
return 0;
}