이번 글에서는 x86 shellcoding에 대해 알아 보겠습니다!
1. Making Win32 Shellcode
shellcode는 아래와 같은 방법으로 만들 수 있습니다.
1. 직접 만든다. ㄷㄷ
2. metasploit를 통해 만든다.
#include <windows.h>
int main()
{
char cmd[] = {'c','a','l','c','\0'};
WinExce(cmd, SW_SHOW);
ExitProcess(0);
}
위 코드를 작성하고 실행하면 calc가 실행됩니다.
Visual Studio에서 디스어셈블리를 확인하면 아래와 같습니다.
C 소스코드를 포함한 불필요한 부분을 제외하고 어셈블리 코드만 추출합니다.
에필로그는 필요 없으니 제외했습니다.
Dependency Walker tool를 통해 kenel32.dll의 base 주소를 구하고 WinExec 함수의 offset를 확인할 수 있습니다.
kenel32.dll의 WinExec 함수의 주소
0x7C800000(Image Base) + 0x000623AD(RVA) = 0x7C8623AD
똑같이 ExitProcess 함수를 확인할 수 있습니다.
kenel32.dll의 ExitProcess 함수의 주소
0x7C800000(Image Base) + 0x0001CAFA(RVA) = 0x7C81CAFA
앞에서 구한 주소를 명시적으로 어셈블리로 작성합니다.
해당 코드를 실행하면 calc를 확인할 수 있습니다!
어셈블리어를 조금 최적화(?)를 시켜 줍니다.
마찬가지로 calc를 확인할 수 있습니다.
어셈블리어에서 기계어를 추출하고 shellcode로 제대로 동작하는지 테스트해 봅니다.
정상적으로 calc가 실행됩니다.
끝!
이 아니다 ㅎㅎ...
위 처럼 작성한 shellcode는 동일한 환경에서만 동작합니다... 쉽게 다른 환경이면 DLL의 버전이 다르고 버전이 다르다??
그 안에 실제 함수의 주소도 달라지므로 로컬에서만 동작합니다..
따라서, 환경에 구애받지 않는 shellcode를 작성해야 합니다.
2. Universal Shellcode <- 프로세스 상에서 함수의 주소 값을 동적으로 구해올 수 있는 코드
Univesal Shellcode가 필요한 이유는 shellcode 상에서 WinAPI함수들을 호출해서 사용하려면 해당 함수들의 주소를 알아야 합니다. 하지만 Windows7 이상의 버전에서는 WinAPI 함수들이 포함되어있는 kernel32.dll의 상위 2byte가 부팅할 때마다 바뀌기 때문에 함수 주소를 하드코딩해서 사용할 수 없습니다.(win7 아래는 dll 버전이 달라서 안됨)
따라서, ELF exploit할 때 libc leak하고 offset 더해서 함수 주소를 구했듯이 shellcode 상에서 kernel32.dll의 base 주소를 구하고 kernel32.dll의 PE header를 읽어서 원하는 함수의 offset를 구한 뒤에 base + offset을 해서 원하는 함수의 주소를 구하는 과정을 필요로 합니다.
32bit용 Universal Shellcode를 제작하는 과정은 아래 블로그를 참고 하자!
3. Metasploit
메타스플로잇으로 만드는 법은 아래 블로그를 참고 하자!
https://t1.daumcdn.net/cfile/tistory/2379FB4B55E566B313
4. 용어 정리
1) API ?
API(Application Programming Interface)란 OS가 애플리케이션을 위해 제공하는 함수의 집합으로 애플리케이션과 디바이스를 연결해주는 역할을 한다.
OS는 시스템 자원들(메모리, 프로세스, 파일 등)을 관리하는 역할을 한다. 애플리케이션이 이러한 자원들을 사용하기 위해서는 커널에게 자원 사용을 요청해야 하며 유저단에서 커널에게 요청할 수 있도록 인터페이스를 구현한 것이 Win32 API를 사용하여 애플리케이션을 만드는 것이다.
2) kernel32.dll ?
윈도우에서 실행되는 모든 애플리케이션들은 내부적으로 윈도우 API 함수를 호출하는 형태이며 기본적으로 필요한 기능들은 DLL 형태로 만들어 OS 안에 내장되어 있다.
모든 프로세스는 기본적으로 kernel32.dll이 메모리에 로딩되며 kernel32.dll은 ntdll.dll을 로딩한다. ntdll.dll의 역할이 유저단에서 커널에 요청하는 작업을 수행하여 애플리케이션이 시스템 자원에 접근할 수 있는 것이다.
3) Win32 API의 핵심 DLL
a. kernel32.dll
부팅시 로드되어 모든 프로그램에 사용되고 커널이 애플리케이션에게 제공할 수 있는 서버스 함수 형태로 존재하며 프로세스, 스레드, 메모리 관리를 한다.
a-1. ntdll.dll
kernel32.dll과 함께 부팅 시 로드되어 모든 프로그램에 사용되며 커널 메모리 영역을 사용할 수 있도록 해주는 역할
유저 모드 애플리케이션들에게 커널 API를 연결하는 역할
'윈도우 버그 헌팅' 카테고리의 다른 글
Easy RM to MP3 Converter(BOF 실습) (0) | 2024.03.14 |
---|---|
Exploit writing tutorial part 10 (0) | 2024.03.08 |
Exploit writing tutorial part 8 (0) | 2024.03.06 |
Exploit writing tutorial part 7 (0) | 2024.03.05 |
Exploit writing tutorial part 6 (0) | 2024.03.01 |