R0 CREW

Интересные куски кода (короткие, без обсуждения)

Постим сюда небольшие интересные куски кода. Обсуждение будет происходить в отдельной теме, которая создана для обсуждения кода.

// Прототип
void function(void* pointer);

// Вызов функции
function(
      	     (       // Используем оператор запятая, для установки данных по указателю
                     *(int *)((char *)(pointer) + sizeof(int)) = (int)(1),
                     *(int *)((char *)(pointer)) = (int)(2),
		
                     // Передаем указатель функции
                     pointer
      	     )
);

Чтобы было понятно, вот упрощенная конструкция:

// здесь "a" будет присвоено "d"
a = (b, c, d)

// конструкция a = (b, c, d) раскрывается так
(((a = b) = c) = d)

Проверка работоспособности шелкода:

#include <Windows.h>

char shellcode[] = "\x90\x90\x90\x90\x90\x90\x90\xcc";

int main(int argc, char** argv)
{
	// Если включен DEP работать не будет
	// ((void(*)())&shellcode[0])();

	// Будет работать всегда
	void* run = VirtualAlloc(0, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	memcpy(run, shellcode, sizeof(shellcode));
	((void(*)())run)();

	return 0;
}

Запуск шелкод из бинарного файла:

#include <cstdio>
#include <Windows.h>

int main(int argc, char* argv[])
{
	HANDLE hFile;
	LPBYTE pSC;
	DWORD dwSize;

	if (argc != 2) { 
		printf("Usage: %s <shellcode.bin file>\n", argv[0]);
		return -1;
	}

	hFile = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL);

	if (hFile == INVALID_HANDLE_VALUE) 
		return -1;

	dwSize = GetFileSize(hFile, NULL);
	pSC = new BYTE[dwSize+1];
	
	if (pSC != NULL) { 
		pSC[0] = '\xCC'; // INT 3
		ReadFile(hFile, pSC+1, dwSize, &dwSize, NULL);
		__asm jmp pSC;
	}

	CloseHandle(hFile);
	return 0;
}

Грязный хак демострирующий измнение адреса возврата из функции. Работоспособность зависит от компилятора и его настроек оптимизации.

#include <cstdlib>

// Прототип
int new_main(void);

// Используется для хранения адреса возврата main()
int g_main_ret = 0;

int main(int argc, char** argv)
{
	int* ret;
	
	ret = (int *)(&ret + 3);	// Устанавливаем указатель на адрес возврата main()	
	g_main_ret = (*ret);		// Сохраняем старый адрес возвра
	(*ret) = (int)new_main;		// Перезаписываем адрес возврата адресом new_main()

	return 0;
}

int new_main()
{
	int* ret;
	ret = (int *)&ret + 3;

	// Меняем адресс возврата new_main() на адрес из g_main_ret
	// Если этого не сделать будет нарушение стека и крэш
	(*ret) = (int)g_main_ret;

	// Используем остановку для демонстрации
	system("PAUSE");

	return 0;
}

Для тех кто иногда путается в сложных объявлениях, подобных этому:

char *(*(**foo [][8])())[];

Объяснение: тут

Подключить TlsCallback, взято от сюда.

#include <windows.h>
 
void NTAPI TLSEntry(PVOID DllHandle, DWORD dwReason, PVOID)
{
         if (dwReason == DLL_THREAD_ATTACH)
         {
                 MessageBox(0, L"DLL_THREAD_ATTACH", L"DLL_THREAD_ATTACH", 0);
         }
 
         if (dwReason == DLL_PROCESS_ATTACH)
         {
                 MessageBox(0, L"DLL_PROCESS_ATTACH", L"DLL_PROCESS_ATTACH", 0);
         }
}
 
#ifdef _WIN64
#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:tls_callback")
#else
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:_tls_callback")
#endif
 
#ifdef _WIN64
#pragma const_seg(".CRT$XLF")
EXTERN_C const
#else
#pragma data_seg(".CRT$XLF")
EXTERN_C
#endif
PIMAGE_TLS_CALLBACK tls_callback = TLSEntry;
#ifdef _WIN64
#pragma const_seg()
#else
#pragma data_seg()
#endif //_WIN64
 
DWORD WINAPI ThreadProc(CONST LPVOID lpParam) 
{
         ExitThread(0);
}
 
 
int main(void)
{
         MessageBox(0, L"hello from main", L"main", 0);
         CreateThread(NULL, 0, &ThreadProc, 0, 0, NULL);
         return 0;
}

Дополнение от Mosc:
https://forum.reverse4you.org/thread/2042

POC для Thread Local Storage, part 3: Compiler and linker support for implicit TLS (собирается с использованием VC 2010 SP1, Platform Toolset=Windows7.1SDK, в т.ч. при использовании msvcrt.lib из DDK/WDK, работает на Windows XP SP3, Windows 7 x64 SP1):

#define NTDDI_VERSION NTDDI_WINXP
#define _WIN32_WINNT _WIN32_WINNT_WINXP

#include "TargetVer.h"

#ifndef STRICT
#define STRICT
#endif

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <windows.h>
#include <wchar.h>
#include <process.h>

void NTAPI TLSCallback(PVOID DllHandle, DWORD Reason, PVOID Reserved);

#ifdef _WIN64
#pragma comment(linker, "/include:_tls_used")
#else // ifdef _WIN64
#pragma comment(linker, "/include:__tls_used")
#endif // ifdef _WIN64

#pragma section(".CRT$XLB", read)
#ifdef __cplusplus
extern "C"
#endif // ifdef __cplusplus
__declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK g_pAddressOfTLSCallback = TLSCallback;
#ifndef _DEBUG
#ifdef _WIN64
#pragma comment(linker, "/include:g_pAddressOfTLSCallback")
#else // ifdef _WIN64
#pragma comment(linker, "/include:_g_pAddressOfTLSCallback")
#endif // ifdef _WIN64
#endif // ifndef DEBUG

void NTAPI TLSCallback(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
	UNREFERENCED_PARAMETER(Reserved);

	wprintf(L"%s procedure called with DllHandle=0x%p, Reason=%d.\n", TEXT(__FUNCTION__), DllHandle, Reason);
}

UINT __stdcall ThreadProcedure(void* arglist)
{
	UNREFERENCED_PARAMETER(arglist);

	return ERROR_SUCCESS;
}

int wmain(int argc, wchar_t* argv[], wchar_t* envp[])
{
	HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, ThreadProcedure, NULL, 0, NULL);

	UNREFERENCED_PARAMETER(argc);
	UNREFERENCED_PARAMETER(argv);
	UNREFERENCED_PARAMETER(envp);

	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);

	return ERROR_SUCCESS;
}

:wink:

Задача: есть адрес, нужно получить имя модуля к которому он относится.

Долго вспоминал как делается, оставлю тут ))

HMODULE hModule = NULL;
char chModuleName[MAX_PATH] = {0};

DWORD addr = (DWORD)GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "CreateFileA" );

if(GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)addr, &hModule) ) {
  if(GetModuleBaseNameA(GetCurrentProcess(), hModule, chModuleName, sizeof(chModuleName))) {
    cout << chModuleName << endl;
  }
}