정보보안 SUA - [정보보안공부] 5주차 과제 - Hooking의 기초

2021. 3. 3. 10:32·리버싱/리버싱 걸음마
728x90
반응형

- [필수 1] Hooking의 정의, 개념 등을 이해합니다. (Link 1)
- [필수 2] 모든 프로세스를 열거합니다. (콘솔 프로그램도 무관. Link 2, 3)
- [필수 3] 지정한 프로세스의 메모리에서 특정 주소의 데이터를 읽거나 원하는 데이터를 덮어씁니다. (Link 4, 5, 6)
- [선택 1] 직접 작성한 프로그램의 실행 흐름을 런타임 API Hooking을 이용하여 바꿔봅니다.
- [선택 2] Hooking 여부를 탐지할 수 있는 방법들을 생각하고 직접 구현해봅니다.

 

Link 1 - en.wikipedia.org/wiki/Hooking

Link 2 - 모든 프로세스 ID 열거 (PSAPI 사용): 

docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes

 

Enumerating All Processes - Win32 apps

The following sample code uses the EnumProcesses function to enumerate the current processes in the system.

docs.microsoft.com

Link 3 - 모든 프로세스 정보 열거 (Tlhel32 사용):

docs.microsoft.com/en-us/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes

 

Taking a Snapshot and Viewing Processes - Win32 apps

The following simple console application obtains a list of running processes.

docs.microsoft.com

Link 4 - Process ID로 Process Handle 얻기:

docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess

 

OpenProcess function (processthreadsapi.h) - Win32 apps

Opens an existing local process object.

docs.microsoft.com

Link 5 - 지정된 프로세스 및 주소로부터 지정된 크기만큼 데이터 읽기: 

docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory

 

ReadProcessMemory function (memoryapi.h) - Win32 apps

Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails.

docs.microsoft.com

Link 6 - 지정된 프로세스 및 주소에 지정된 크기 만큼 데이터 쓰기:

docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory

 

WriteProcessMemory function (memoryapi.h) - Win32 apps

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.

docs.microsoft.com

[필수1] Hooking의 정의 및 개념 


후킹(Hooking)

리버싱에서 후킹은 정보를 가로채며, 실행 흐름을 변경하고 기존의 프로그램과는 다른 기능을 제공하는 기술.

 

후크(Hook)

후킹 시에 영향을 끼친 함수, 이벤트, 메세지를 처리하는 코드

 


[필수 2-1] 모든 프로세스를 ID 열거 (PSAPI 사용)


EnumProcesses 함수를 사용하여 각 프로세스 개체에 대한 프로세스 식별자(ID)를 검색하는 코드 및 결과

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>

// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1

void PrintProcessNameAndID( DWORD processID )
{
    TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");

    // Get a handle to the process.

    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                                   PROCESS_VM_READ,
                                   FALSE, processID );

    // Get the process name.

    if (NULL != hProcess )
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
             &cbNeeded) )
        {
            GetModuleBaseName( hProcess, hMod, szProcessName, 
                               sizeof(szProcessName)/sizeof(TCHAR) );
        }
    }

    // Print the process name and identifier.

    _tprintf( TEXT("%s  (PID: %u)\n"), szProcessName, processID );

    // Release the handle to the process.

    CloseHandle( hProcess );
}

int main( void )
{
    // Get the list of process identifiers.

    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;

    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
    {
        return 1;
    }


    // Calculate how many process identifiers were returned.

    cProcesses = cbNeeded / sizeof(DWORD);

    // Print the name and process identifier for each process.

    for ( i = 0; i < cProcesses; i++ )
    {
        if( aProcesses[i] != 0 )
        {
            PrintProcessNameAndID( aProcesses[i] );
        }
    }

    return 0;
}

[필수2-1] 결과

A - EnumProcesses 함수를 사용하여 프로세스 목록을 가져온다.

B -  각 프로세스에 대해 main함수는 PrintProcesessNameAndID 함수를 호출하여 프로세스 식별자를 전달한다.

C - PrintProcesessNameAndID는 차례로 OpenProcess 함수를 호출하여 프로세스 핸들을 얻는다.

D - PrintProcesessNameAndID는 EnumProcessModules 함수를 호출하여 모듈핸들을 얻는다.

F - PrintProcesessNameAndID는 GetModuleBaseName 함수를 호출하여 실행파일의 이름을 얻고 프로세스 식별자와 함께 이름이 표시된다.


 

 

[필수2-2] 모든 프로세스 정보 열거 (Tlhel32 사용)


#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>

//  Forward declarations:
BOOL GetProcessList( );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );

int main( void )
{
  GetProcessList( );
  return 0;
}

BOOL GetProcessList( )
{
  HANDLE hProcessSnap;
  HANDLE hProcess;
  PROCESSENTRY32 pe32;
  DWORD dwPriorityClass;

  // Take a snapshot of all processes in the system.
  hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  if( hProcessSnap == INVALID_HANDLE_VALUE )
  {
    printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
    return( FALSE );
  }

  // Set the size of the structure before using it.
  pe32.dwSize = sizeof( PROCESSENTRY32 );

  // Retrieve information about the first process,
  // and exit if unsuccessful
  if( !Process32First( hProcessSnap, &pe32 ) )
  {
    printError( TEXT("Process32First") ); // show cause of failure
    CloseHandle( hProcessSnap );          // clean the snapshot object
    return( FALSE );
  }

  // Now walk the snapshot of processes, and
  // display information about each process in turn
  do
  {
    _tprintf( TEXT("\n\n=====================================================" ));
    _tprintf( TEXT("\nPROCESS NAME:  %s"), pe32.szExeFile );
    _tprintf( TEXT("\n-------------------------------------------------------" ));

    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
    if( hProcess == NULL )
      printError( TEXT("OpenProcess") );
    else
    {
      dwPriorityClass = GetPriorityClass( hProcess );
      if( !dwPriorityClass )
        printError( TEXT("GetPriorityClass") );
      CloseHandle( hProcess );
    }

    _tprintf( TEXT("\n  Process ID        = 0x%08X"), pe32.th32ProcessID );
    _tprintf( TEXT("\n  Thread count      = %d"),   pe32.cntThreads );
    _tprintf( TEXT("\n  Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
    _tprintf( TEXT("\n  Priority base     = %d"), pe32.pcPriClassBase );
    if( dwPriorityClass )
      _tprintf( TEXT("\n  Priority class    = %d"), dwPriorityClass );

    // List the modules and threads associated with this process
    ListProcessModules( pe32.th32ProcessID );
    ListProcessThreads( pe32.th32ProcessID );

  } while( Process32Next( hProcessSnap, &pe32 ) );

  CloseHandle( hProcessSnap );
  return( TRUE );
}


BOOL ListProcessModules( DWORD dwPID )
{
  HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
  MODULEENTRY32 me32;

  // Take a snapshot of all modules in the specified process.
  hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
  if( hModuleSnap == INVALID_HANDLE_VALUE )
  {
    printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
    return( FALSE );
  }

  // Set the size of the structure before using it.
  me32.dwSize = sizeof( MODULEENTRY32 );

  // Retrieve information about the first module,
  // and exit if unsuccessful
  if( !Module32First( hModuleSnap, &me32 ) )
  {
    printError( TEXT("Module32First") );  // show cause of failure
    CloseHandle( hModuleSnap );           // clean the snapshot object
    return( FALSE );
  }

  // Now walk the module list of the process,
  // and display information about each module
  do
  {
    _tprintf( TEXT("\n\n     MODULE NAME:     %s"),   me32.szModule );
    _tprintf( TEXT("\n     Executable     = %s"),     me32.szExePath );
    _tprintf( TEXT("\n     Process ID     = 0x%08X"),         me32.th32ProcessID );
    _tprintf( TEXT("\n     Ref count (g)  = 0x%04X"),     me32.GlblcntUsage );
    _tprintf( TEXT("\n     Ref count (p)  = 0x%04X"),     me32.ProccntUsage );
    _tprintf( TEXT("\n     Base address   = 0x%08X"), (DWORD) me32.modBaseAddr );
    _tprintf( TEXT("\n     Base size      = %d"),             me32.modBaseSize );

  } while( Module32Next( hModuleSnap, &me32 ) );

  CloseHandle( hModuleSnap );
  return( TRUE );
}

BOOL ListProcessThreads( DWORD dwOwnerPID ) 
{ 
  HANDLE hThreadSnap = INVALID_HANDLE_VALUE; 
  THREADENTRY32 te32; 
 
  // Take a snapshot of all running threads  
  hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
  if( hThreadSnap == INVALID_HANDLE_VALUE ) 
    return( FALSE ); 
 
  // Fill in the size of the structure before using it. 
  te32.dwSize = sizeof(THREADENTRY32); 
 
  // Retrieve information about the first thread,
  // and exit if unsuccessful
  if( !Thread32First( hThreadSnap, &te32 ) ) 
  {
    printError( TEXT("Thread32First") ); // show cause of failure
    CloseHandle( hThreadSnap );          // clean the snapshot object
    return( FALSE );
  }

  // Now walk the thread list of the system,
  // and display information about each thread
  // associated with the specified process
  do 
  { 
    if( te32.th32OwnerProcessID == dwOwnerPID )
    {
      _tprintf( TEXT("\n\n     THREAD ID      = 0x%08X"), te32.th32ThreadID ); 
      _tprintf( TEXT("\n     Base priority  = %d"), te32.tpBasePri ); 
      _tprintf( TEXT("\n     Delta priority = %d"), te32.tpDeltaPri ); 
      _tprintf( TEXT("\n"));
    }
  } while( Thread32Next(hThreadSnap, &te32 ) ); 

  CloseHandle( hThreadSnap );
  return( TRUE );
}

void printError( TCHAR* msg )
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;

  eNum = GetLastError( );
  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
         sysMsg, 256, NULL );

  // Trim the end of the line and terminate it with a null
  p = sysMsg;
  while( ( *p > 31 ) || ( *p == 9 ) )
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );

  // Display the message
  _tprintf( TEXT("\n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}

[필수2-2] 결과

A - GetProcessList 함수는 CreateToolhelp32Snapshot을 사용하여 시스템에서 현재 실행중인 프로세스의 스냅 샷을 만든 다음 Process32First 및 Process32Next를 사용하여 스냅 샷에 기록된 목록을 살펴본다.

B -  차례대로 각 프로세스에 대해 모듈목록탐색에 설명 도니 함수와 스레드 목록탐색에 설명된 함수를 GetProcessList로 함수로 호출한다.

C -printError은 일반적으로 보안 제한으로 인해 발생하는 오류의 원인을 표시한다.


 [필수 3] 지정한 프로세스의 메모리에서 특정 주소의 데이터를 읽거나 원하는 데이터를 덮어쓴다.


OpenProcess function - 기존 로컬 프로세스 개체를 열어주는 함수

ReadProcessMemory function - 프로세스 메로리를 읽는 함수

WriteProcessMemory function - 지정된 프로세스의 메모리 영역에 데이터를 쓰는 함수

현재 사용중인 카카오톡 PID 11224. 위의 함수를 이용하여 [필수3]과제를 해보겠습니다.

(참고 - debugjung.tistory.com/entry/%ED%8E%8C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%95%88%EC%97%90-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B3%A0-%EC%9D%BD%EA%B3%A0-%EC%93%B0%EA%B8%B0)

 

#include <stdio.h>
#include <windows.h>

int main() {
	HANDLE num;
	
	if ((num = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 11224)) == NULL)
		printf("Error\n\n");
	else
		printf("Handle: %d\n\n");

	return 0;
}

 

 

#include <stdio.h>
#include <windows.h>
#include <memoryapi.h>
int main() {
	HANDLE num;
	
	if ((num = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 11224)) == NULL)
		printf("Error\n\n");
	else
		printf("Handle: %d\n\n",num);

	DWORD buf = 0;
	
	if (ReadProcessMemory(num, (LPVOID)0xA70000, &buf, sizeof(DWORD), NULL) != 0)
	{ 
		buf++;
		WriteProcessMemory(num, (LPVOID)0xA70000, (LPCVOID)&buf, sizeof(DWORD), NULL);
	}
	return 0;
}

[필수3] 결과 값

 

728x90
반응형

'리버싱 > 리버싱 걸음마' 카테고리의 다른 글

정보보안 SUA - [정보보안공부] 7주차 과제 - DLL Injection 수행  (0) 2021.03.17
정보보안 SUA - [정보보안공부] 6주차 과제 - 런타임 API Hooking 수행  (0) 2021.03.11
정보보안 SUA - [정보보안공부] 4주차 과제 - Windows 데스크톱 앱 개발  (0) 2021.02.26
정보보안 SUA - [정보보안공부] 3주차 과제 - 리버싱 로드 맵 및 PE로더  (0) 2021.02.24
정보보안 SUA - [정보보안공부] 2주차 과제 - Windows 데스크톱 앱 개C/C++ 언어의 다양한 개념들이 x86 어셈블리 언어로 변환 결과물  (0) 2021.02.05
'리버싱/리버싱 걸음마' 카테고리의 다른 글
  • 정보보안 SUA - [정보보안공부] 7주차 과제 - DLL Injection 수행
  • 정보보안 SUA - [정보보안공부] 6주차 과제 - 런타임 API Hooking 수행
  • 정보보안 SUA - [정보보안공부] 4주차 과제 - Windows 데스크톱 앱 개발
  • 정보보안 SUA - [정보보안공부] 3주차 과제 - 리버싱 로드 맵 및 PE로더
Royal!
Royal!
Bachelor of Arts. Bachelor of Science in Engineering. Master of Science in Engineering (In Progress). Job Title: Infrastructure & Security & Cloud Engineer. Etc: Mentor at Fourth Industrial Revolution Center.
  • Royal!
    Security
    Royal!
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 운영체제
      • 네트워크
      • 클라우드
      • 서버
      • Container
      • 프로그래밍
        • Python_혼자 끄적끄적
        • Python_AI(영상처리)
        • 빅데이터
        • C_정보올림피아드 Language_Coder
        • C_QnA
      • 자격증
        • 정보보안기사
        • 정보처리기사
        • ADsP
        • CPPG
        • 보안법률
        • NCA~NCP
        • AWS Certified Solutions Arc..
      • 리버싱
        • 리버싱 걸음마
      • Wargame & CTF
        • Hackerschool FTZ
      • 기타 교육
        • KISA 정보보호제품실습군
        • 빅데이터_분석실무
        • 시큐어코딩진단전문교육(호남정보보호센터)
        • SW테스트 전문가 과정(ISTQB CTFL자격)
        • 정보보호 컨설팅 전문가 양성과정
      • 기타
        • 면접일지
        • 기타
        • 인턴활동
        • 논문 요약
      • K-Shield Jr
        • 악성코드분석
        • 침해사고분석
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    nce덤프
    getuid
    rest api 공부
    rest api 정리
    304코드
    swtich frame
    fragment-free
    switch forwarding mode
    rest api 문법
    getuid()
    kernel 사용자 모드
    rest api 논문
    redirect 304
    kernel 구성요소
    restful api 개념
    rest api 제약조건
    nce dump
    스위치 프레임 포워딩 방식
    네이버클라우드 ftp 설정
    euid가 중요한 이유
    uid란
    304 code
    geteuid()
    kernel모드
    geteuid
    스위치 프레임 동작 방식
    상태코드 304
    l2 스위치 프레임 전달 방식
    euid란
    rest api 아키텍처
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Royal!
정보보안 SUA - [정보보안공부] 5주차 과제 - Hooking의 기초
상단으로

티스토리툴바