
Win32 및 커널 남용 기법 (펜테스터용)
모의 침투 테스터와 레드 팀원을 위한 Win32 및 커널 악용 기술, @UVision과 @RistBS 제작
개발 모드 활성화, 어떤 도움이라도 환영합니다 :)
DOS_HEADER : PE의 첫 번째 헤더로, MS DOS 메시지("이 프로그램은 DOS 모드에서 실행할 수 없습니다...."), MZ 헤더(PE 식별용 매직 바이트) 및 일부 스텁 콘텐츠를 포함합니다.IMAGE_NT_HEADER : PE 파일 서명, 파일 헤더 및 선택 헤더를 포함합니다.SECTION_TABLE : 섹션 헤더를 포함합니다.SECTIONS : 헤더는 아니지만 알아두면 유용합니다. PE의 섹션들입니다.자세한 내용 : https://www.researchgate.net/figure/PE-structure-of-normal-executable_fig1_259647266
IAT 및 ILT 절대 주소를 검색하는 간단한 PE 파싱:
GetModuleHandleA(NULL);BaseAddress+PIMAGE_DOS_HEADER.e_lfnanew (RVA NT_HEADER)OptionnalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]IMAGE_DATA_DIRECTORY.VirtualAddress (IMAGE_IMPORT_DIRECTORY의 RVA)BaseAddress + IMAGE_IMPORT_DIRECTORY.VirtualAddress (IMAGE_IMPORT_DESCRIPTOR의 RVA)EAT는 PE에서 내보낸 모든 함수를 확인하고 DLL도 확인합니다. IMAGE_EXPORT_DIRECTORY 구조에 정의되어 있습니다:```c
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name; // name of DLL
DWORD Base; // first ordinal number
DWORD NumberOfFunctions; // number of entries in EAT
DWORD NumberOfNames; // number of entries in (1) (2)
DWORD AddressOfFunctions; // RVA EAT and contains also RVA of exported functions
DWORD AddressOfNames; // Pointer array contains address of function names
DWORD AddressOfNameOrdinals; // Pointer array contains address of ordinal number of functions (index in AddressOfFunctions)
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
Please note that the EAT is defined in a DLL, not in a "real" PE (a PE will use the EAT of a loaded dll to resolve pointers to functions it want to use).
### 함수 주소 확인
**함수 주소 사용**
무엇을 기다리고 있나요? 이 함수를 찾으세요!
**서수 번호 사용**
서수 번호는 `AddressOfFunctions` 배열에서 해당 함수 주소를 가리키는 **인덱스 위치**입니다. 아래와 같이 함수의 올바른 주소를 **검색하는 데** 사용할 수 있습니다.
주어진 서수 번호 3으로 해당 주소(Addr4)를 찾아보겠습니다.
- **AddressOfFunctions** : *Addr1 Addr2 Addr3 Addr4 .... AddrN*
- **AdressOfNameOrdinals** : *2 5 7 3 ... N*
우리가 찾는 주소는 (0부터 시작하여) 3번째 위치에 있으며, 서수 번호는 이 주소의 **인덱스**에 해당합니다.
**함수 이름 사용**
AddressOfNames 배열의 N번째 요소는 AddressOfNameOrdinals 배열의 N번째 요소에 대응합니다. 주어진 이름을 사용하여 해당 서수 번호를 검색한 다음, 이 번호를 사용해 함수 주소를 찾을 수 있습니다.
## Import Address Table (IAT)
- PE 로더는 어떤 주소가 어떤 함수에 해당하는지 알지 못합니다. IAT를 통해 문제를 해결해 봅시다.
- IMAGE_IMPORT_DIRECTORY 구조체에 정의됩니다:```c
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
DWORD Characteristics;
DWORD OriginalFirstThunk; // RVA to ILT
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name; // RVA of imported DLL name
DWORD FirstThunk; // RVA to IAT
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
요약하자면, IAT는 PE가 로드된 DLL(ntdll, kernel32...)에서 가져온 여러 함수에 대한 포인터를 포함하는 테이블입니다.
자세한 코드 예제는 여기 : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/miscellaneous/iat_parser.cpp
PE가 가져온 모든 DLL에는 자체 ILT가 있습니다.``` Absolute address of ILT = BaseAddress + OriginalFirstThunk (IAT)
가져온 DLL에 있는 모든 함수 이름을 포함합니다.
<br>
## SeDebug 권한 활성화
**SeDebug** 권한은 Windows 권한 목록에서 가장 "탐나는" 권한입니다. 이 권한을 사용하면 승인된 모든 프로세스를 "디버그"할 수 있으며, 이는 ```PROCESS_ALL_ACCESS``` 권한으로 핸들을 여는 것과 같은 여러 공격적 작업으로 해석될 수 있습니다.
사용자 모드에서 이 권한을 활성화하려면 다음과 같은 함수를 사용해야 합니다:```cpp
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;