1. 세그먼트 레지스터와 GDT( global Descriptor Table )
-
- Segment Register
1) DS, CS 는 Table의 인덱스를 가리킨다.
2) mov dword ptr DS[0x1000], 10 : DS레지스터리로부터 1000번지 이동 상대적주소.
2. Data Structure
- TEB안에는 PEB를 가리키는 포인터가 있다. FS[ 주소 ] : TEB의 정보를 읽을 수 있는 레지스터!!
- PEB(Process Enviroment Block) : 프로세스를 관리하기 위해 User Mode에 둔다.
- 직접 접근이 가능하므로 조사하면 많은 정보를 볼 수 있다. ex) dt nt!_PEB ( WinDbg 를 활용하자! )
-
index | address | size | access |
0 | 1000 | 5k | R/W |
1 | 2000 | 3k | R |
- Segment Register
1) DS, CS 는 Table의 인덱스를 가리킨다.
2) mov dword ptr DS[0x1000], 10 : DS레지스터리로부터 1000번지 이동 상대적주소.
2. Data Structure
- TEB안에는 PEB를 가리키는 포인터가 있다. FS[ 주소 ] : TEB의 정보를 읽을 수 있는 레지스터!!
- PEB(Process Enviroment Block) : 프로세스를 관리하기 위해 User Mode에 둔다.
- 직접 접근이 가능하므로 조사하면 많은 정보를 볼 수 있다. ex) dt nt!_PEB ( WinDbg 를 활용하자! )
2. Kernel 상속을 활용한 리다이렉션( 표준출력을 Console창에서 다른곳으로 바꾸는 작업 )
- STARTUPINFO를 활용한다. 잘 알아보면 하는일이 너무많다...
- Handle의 공유 문제 : Duplicate 는 떠있는 상태에서 복사해준다.
- 상속은 이제 만들어진 것에서 유용하다. 부모에게 그대로 상속받는다면 똑같은 Handle이 생성..
- Kernel Object는 기본적으로 비상속 모드이다 이를 SetHandleInfomation 으로 바꿔준다.
- STARTUPINFO를 활용한다. 잘 알아보면 하는일이 너무많다...
more..
- Handle의 공유 문제 : Duplicate 는 떠있는 상태에서 복사해준다.
- 상속은 이제 만들어진 것에서 유용하다. 부모에게 그대로 상속받는다면 똑같은 Handle이 생성..
- Kernel Object는 기본적으로 비상속 모드이다 이를 SetHandleInfomation 으로 바꿔준다.
HANDLE hRead, hWrite;
CreatePipe( &hRead, &hWrite, 0, 1024 );
SetHandleInformation( hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
CreatePipe( &hRead, &hWrite, 0, 1024 );
SetHandleInformation( hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
3. 프로세스 열거
- User : Kernel32.dll ( ToolhelpAPI ) , ntdll.dll ( ZwQuerySystemInformation )
- Kernel : EPROCESS - EPROCESS - EPROCESS -.. // 링크드리스트로 열거 되어 동기화 되고 있다.
- kernel32.dll 은 NT4.0에서는 지원이 안된다. 대신에 PSAPI.dll 이 있다.
- 프로세스 열거시 목록을 SnapShot 해둔다. ( 프로세스가 사라질 경우를 대비.. )
- User : Kernel32.dll ( ToolhelpAPI ) , ntdll.dll ( ZwQuerySystemInformation )
- Kernel : EPROCESS - EPROCESS - EPROCESS -.. // 링크드리스트로 열거 되어 동기화 되고 있다.
- kernel32.dll 은 NT4.0에서는 지원이 안된다. 대신에 PSAPI.dll 이 있다.
- 프로세스 열거시 목록을 SnapShot 해둔다. ( 프로세스가 사라질 경우를 대비.. )
// 프로세스의 목록을 메모리 어딘가에 보관(snapshot)해 둔다.
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
4. 특권얻기
- MSGINA.dll : 로그인창의 다이얼로그가 들어있다.
- 사용자가 지나dll을 다시 만들어서 로그인 과정을 바꾸는 것도 가능하다.
- Access Token에는 사용자의 권한이 기록되어 있다.
- MSGINA.dll : 로그인창의 다이얼로그가 들어있다.
- 사용자가 지나dll을 다시 만들어서 로그인 과정을 바꾸는 것도 가능하다.
- Access Token에는 사용자의 권한이 기록되어 있다.
BOOL EnablePrimary( HANDLE hProcess, // 권한을 부여할 프로세스
char* pri, // 권한을 나타내는 문자열
BOOL bEnable // 가능/불가능 여부
)
{
HANDLE hToken;
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );
// 문자열로 되어 있는 권한ID( LUID, 64비트 정수 )로 변경한다.
LUID luid;
LookupPrivilegeValue(
".", // PC이름
pri, // 권한이름
&luid ); // luid를 담을 변수
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1; // 갯수
tp.Privileges[0].Luid = luid; // 권한 ID
tp.Privileges[0].Attributes= bEnable ? SE_PRIVILEGE_ENABLED : 0;
return AdjustTokenPrivileges( hToken, 0, &tp, sizeof(tp), 0, 0 );
}
char* pri, // 권한을 나타내는 문자열
BOOL bEnable // 가능/불가능 여부
)
{
HANDLE hToken;
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );
// 문자열로 되어 있는 권한ID( LUID, 64비트 정수 )로 변경한다.
LUID luid;
LookupPrivilegeValue(
".", // PC이름
pri, // 권한이름
&luid ); // luid를 담을 변수
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1; // 갯수
tp.Privileges[0].Luid = luid; // 권한 ID
tp.Privileges[0].Attributes= bEnable ? SE_PRIVILEGE_ENABLED : 0;
return AdjustTokenPrivileges( hToken, 0, &tp, sizeof(tp), 0, 0 );
}