handmade native API decompile - symnoisy

Download Report

Transcript handmade native API decompile - symnoisy

HandMade Native API
Decomplie
symnoisy@3c1c
http://symnoisy.tistory.com
[email protected]
0
유정빈
Symnoisy.tistory.com
3c1c.tistory.com
시스템 해킹
리버싱
현 KSIA 연합원
1
INDEX.
API?
Native API?
System call mechanism
2
INDEX.
Compiler & compile
Decompiler & decompile
Native API Decompile
3
1
API?
.
• Application programming Interface
• 운영체제가 어플리케이션과 통신을 위
해서 제공하는 함수의 모음
4
1
API?
.
WIn32 interface DLL과 컴포넌트 와의 관계
5
2
Native API?
.
WIn32 interface DLL과 컴포넌트 와의 관계
6
2
System call mechanism
.
• 유저모드에서 커널모드를 호출하기 위한 방법
2E!2E!2E!2E!
(주로 App이 OS API를 호출할때 자주 발생)
• KiSystemService, KiServiceTable
• SYSENTER
7
3
Native API?
.
• 메모리 관리자,I/O 시스템,객체관리자,프로세스
와 스레드에 직접접근할 수 있는 인터페이스 제
공
• EX)NtCreateFIle(), ZwCreateFile()
8
4
Compiler & Compile
.
C
Compiler
목적코드
(기계어코드)
9
+)
.
Disassem
어셈블리
목적코드
Disassem.
언어
10
5
Decompiler & Decompile
.
실행
바이너리
Decompile.
고급언어
Ex)C
11
이번 발표의 main:
전제 :)
리얼 극한의 상황, IDA 안깔려있고, 인터넷에서 문서 또한 찾을수 없다 가정.
우리에게 주어진건 해당 API에서 함수 일부를 끌어와서 사용하는 프로그램 달랑 하나
문서화 되지 않은(native) API를 찾아보자
12
6
Native API decompile
.
Ntdll!Generic Table
RTL 함수(RunTime Library)
OS와 상호작용 없이 단순히 문자열이나 데이터 처리와 같
은 일상적으로 요구되는 기능을 제공하는 함수
13
6
Native API decompile
.
14
6
Native API decompile
.
15
그렇다면, 가장 처음 접근해야 할 API는
무엇인가?
그렇다면 이제부터 분석 ㄱㄱ
16
6
Native API decompile
.
RtlInitializeGenericTable
17
6
Native API decompile
.
RtlInitializeGenericTable
18
6
EAX= 1st parameter
ECX =2nd parameter
EDX=0 .
Native API decompile
UnknownStruct->Memb1=0;
UnknownStruct->Memb3=&UnknownStruct->Memb2;
UnknownStruct->Memb2=&UnknownStruct->Memb2;
UnknownStruct->Memb4=&UnknownStruct->Memb2;
Offset18(decimal 24, 7th)=2nd param
value
Offset1C(decimal 28 8th)=3rd param
value
Offset20(decimal 32, 9th)=4th param
value
Offset14(decimal 20,4th)=0
Offset10(decimal 16,3rd)=0
Offset24(decimal 36, 8th)=5th param
value
UnknownStruct->Memb7= Param2;
UnknownStruct->Memb8= Param3;
UnknownStruct->Memb9= Param4;
Offset14(decimal 20,4th)=0
Offset10(decimal 16,3rd)=0
UnknownStruct->Memb8= Param5;
19
6
Native API decompile
.
Struct TABLE
{
}
UNKNOWN
Member1;
UNKNOWN_PTR
Member2;
UNKNOWN_PTR
Member3;
UNKNOWN_PTR
Member4;
UNKNOWN
Member5;
UNKNOWN
Member6;
UNKNOWN
Member7;
UNKNOWN
Member8;
UNKNOWN
Member9;
UNKNOWN
Member10;
20
6
Native API decompile
.
RtlInitializeGenericTable
21
6
Native API decompile
.
[summary]
도출해
낼수
있는안에는
결론: offset+4부터 시작해서 세개의 포인터 그
루트 데이터
구조체
•Index 번호와 테이블 구조체에
대한 포인터를 사용한다.
룹이 존재한다
이 포인터들은 다른 세 포인터 그룹을 가리키고 처음에는 자신들을
가리키게 초기화되어
엔트리가 차면 변경
•테이블의
엔트리를있다.(가정)이는
반환 값으로 테이블에
반환한다(가정)
RtlGetElementGenericTable
ECX =1 parameter
st
EDX=6th parameter
EAX=4th parameter
RtlGetElementGenerticTable 함수는 이 포인터중 4번째 파라미터값 ESI=5th parameter
•12를에더함으로써
부분이
아닌 데이터
부분을
반환한다.
12를 더해서 헤더
반환. 12는
세포인터의
전체 크기와
동일
EDI= 2nd parameter
if(Param2 == 0xffffffff)
th Parameter)
AdjustedIndexNumber(EBX)
=IndexNumber(EDI)+1
테이블 +
데이터
구조체에
대한 포인터를
사용하고,포인터인
테이블에
대한
•Offset
0x10(5
=>세번째
Offset+C가 가리키는 인덱스
return
0;
th parameter)
index 번호를
사용한다
( 7C992501>6
주소의
비교문)
if( IndexNumber==
0xffffffff||(AdjustedIndexNumber
•Offset +C(4th Parameter) => 메모리를
가리키는
return
0; 포인터
(7C992554 주소의 ADD EAX(4th Parameter에 0C를 더해줌)
22
6
Native API decompile
.
RtlGetElementGenericTable
헬 게이트 Open .. 애도
요
23
6
ECX =1st parameter
EDX=6th parameter
EAX=4th parameter
(메모리를 가리키는 포인터)
ESI=5th parameter
(세번째 포인터(memb4,EAX)가 가
리키는인덱스
EDI= 2nd parameter
LOOP1 :)
EBX = Table Index 값
각 엔트리의 offset +4값을 취하면서 낮은 인덱스 방향
4th parameter: loop 돌면서 찾아낸 엔트리
포인터
일단
보류
5th parameter:해당 엔트리에 대한 인덱스
빼기연산=비교연산
ESI-EBX=0 or ESI =EBX
ESI-EBX= 검색 전체 개수
LOOP ESI !=EBX
Case: ESI>EBX
Native API decompile
.
RtlGetElementGenericTable(로직 이해)
오잉?
24
6
Native API decompile
.
EDX= EDX-(EBX)Table Index+1
EDI=EDI(=EBX)TableIndex-ESI
ECX =1st parameter
EDX=6th parameter
EAX=4th parameter
(result 가리키는 포인터)
ESI=5th parameter
(result 엔트리 가리키는인덱스
EDI= 2nd parameter
EBX = Table Index 값
RtlGetElementGenericTable(로직 이해)
EDX(6th Parameter)=리스트의 끝 ~찾고자하는 엔트리 인
덱스 까지의 거리
ESI< EBX (==인경우는 앞
EDI(2nd Parameter)=찾고자하는 엔트리 인덱스 ~마지막 에서 윗줄에서 이미처리)
으로 찾은 엔트리 인덱스 까지의 거리
(=마지막인덱스)
25
ECX =1st parameter
EDX=6th parameter
(처음~끝 인덱스 거리)
.
EAX=4th parameter
(메모리를 가리키는 포인터)
ESI=5th parameter
(세번째 포인터(memb4)가 가리
키는인덱스
EDI= 2nd parameter
(마지막Index)
th
EDX(6 Parameter)=처음부터 끝까지 엔트리 인덱스의 EBX = Table Index 값
거리
EDI(2nd Parameter)=찾고자하는 엔트리 인덱스 ~마지막
으로 찾은 엔트리 인덱스 까지의 거리
(=마지막인덱스)
6
Native API decompile
RtlGetElementGenericTable(로직 이해)
26
6
Native API decompile
.
ECX =1st parameter
EDX=6th parameter
EAX=4th parameter
(메모리를 가리키는 포인터)
ESI=5th parameter
(세번째 포인터(memb4)가 가리
키는인덱스
EDI= 2nd parameter
EBX = Table Index 값
RtlGetElementGenericTable (로직 이해)
27
6
Native API decompile
.
RtlGetElementGenericTable
Struct TABLE
{
PVOID UnKnown1;
LIST_ENTRY
LIST_ENTRY
*SomeEntry;
LIST_ENTRY
*LastElementFound;
ULONG
ULONG
ULONG
}
*LLHead;
LastElementIndex;
NumberOfElements;
Unknown1;
ULONG
Unknown2;
ULONG
Unknown3;
ULONG
Unknown4;
28
6
Native API decompile
.
RtlGetElementGenericTable
PVOID stdcall RtlGetElementGenericTable(TABLE *Table,ULONG ElementToGet)
{
ULONG TotalElementCount=Table->NumberOfElements;
LIST_ENTRY *ElementFound=Table->LastElementFound;
ULONG LastIndexFound=Table->LastElementIndex;
ULONG AdjustedElementToGet=ElementToGet+1;
if(ElementToGet==-1 || AdjustedElementToGet>ToTalElementCount)
if(AdjustedElementToGet != LastIndexFound)
{
if(LastIndexFound >AdjustedElementToGet)
{
ULONG HalfWayFromLastFound = LastIndexFound/2;
if(AdjustedElementToGet >HalfWayFromLastFound)
{
ULONG ElementToGo=LastIndexFound –AdjustedElementToGet;
while(ElementsToGo--)
ElementFound=ElementFound ->Blink;
}
29
6
Native API decompile
.
RtlGetElementGenericTable
else
{
ULONG ElementsToGo = AdjustedElementToGet;
ElementFound=(LIST_ENTRY*) &Table->LLHead;
while(ElementsToGo--)
ElementFound = ElementFound ->Flink;
}
}
else
{
ULONG ElementsToLastFound=AdjustedElementToGet – LastIndexFound;
ULONG ElementsToEnd = TotalElementCount – AdjustedElementToGet +1;
if (ElementsToLastFound <= ElementsToEnd)
{
while(ElementsToLastFound -- )
ElementFound = ElementFound->Flink;
}
30
6
Native API decompile
.
RtlGetElementGenericTable
else
{
ElementFound = (LIST_ENTRY *)&Table->LLHead;
while(ElementsToEnd--)
ElementFound = ElementFound->Blink;
}
}
Table->LastElementFound= ElementFound;
Talbe->LastElementIndex = AdjustedElementToGet;
}
return (PVOID) ((PULONG)ElementFound +3);
}
31
결론:
• 디컴파일은 장인 정신을 요구한다
(하지만 꼭 한번은 해봐야 한다)
• 디컴파일러를 감사히 여기며 쓰자
32
33
결론:
• 디컴파일은 장인 정신을 요구한다
(하지만 꼭 한번은 해봐야 한다)
(이거로 발표는 하지말자 ;)
• 디컴파일러를 감사히 여기며 쓰자
(하지만 뭉개질때는 내가 분석해야한다)
34
THANK YOU!
Q&A
symnoisy.tistory.com
facebook.com/jungbin.yu
35