HandMade Native API Decomplie

Slides:



Advertisements
Similar presentations
프로그램이란 프로그램 생성 과정 프로젝트 생성 프로그램 실행 컴퓨터를 사용하는 이유는 무엇인가 ? – 주어진 문제를 쉽고, 빠르게 해결하기 위해서 사용한다. 컴퓨터를 사용한다는 것은 ? – 컴퓨터에 설치 혹은 저장된 프로그램을 사용하는 것이다. 문제를 해결하기 위한.
Advertisements

1. 2 차원 배열  배열은 동일한 데이터 유형으로 여러 개의 변수를 사용할 경우 같은 이 름으로 지정하여 간편하게 사용할 수 있도록 하는 것으로서 앞에서 1 차원 배열을 공부하였습니다.  2 차원 배열은 바둑판을 생각하면 되며, 1 차원 배열에서 사용하는 첨자를 2.
재료수치해석 HW # 박재혁.
2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
코크파트너 설치 가이드 Window 7.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
1장. 이것이 C 언어다.. 1장. 이것이 C 언어다. 프로그래밍 언어 1-1 C 언어의 개론적 이야기 한글, 엑셀, 게임 등의 프로그램을 만들 때 사용하는 언어 ‘컴퓨터 프로그래머’라는 사람들이 제작 C 언어(C++ 포함)를 가장 많이 사용함.
제 9 장 구조체와 공용체.
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
컴퓨터 프로그래밍 기초 [Final] 기말고사
Power Java 제2장 자바 개발 도구.
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 12. 포인터의 이해.
07. 디바이스 드라이버의 초기화와 종료 김진홍
CHAPTER 02 OpenCV 개요 PART 01 영상 처리 개요 및 OpenCV 소개.
P150 문제를 프로그래밍 할 것 Source file (헤더파일포함), 실행화면 (학번_이름_1.txt)
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
DK-128 ADC 실습 아이티즌 기술연구소
18강. 데이터 베이스 - II JDBC 살펴보기 Statement객체 살펴보기 Lecturer Kim Myoung-Ho
17강. 데이터 베이스 - I 데이터 베이스의 개요 Oracle 설치 기본적인 SQL문 익히기
자료구조: CHAP 4 리스트 (3) 순천향대학교 컴퓨터공학과 하 상 호.
TCP/IP Socket Programming…
11장. 1차원 배열.
CHAP 12. 리소스와 보안.
Method & library.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
인터넷응용프로그래밍 JavaScript(Intro).
Seoul National University
이름 : 황 상 두 전화번호 : 이메일 : PinTool 이름 : 황 상 두 전화번호 : 이메일 :
10장 tkinter로 GUI 만들기.
30강 JAVA 그래픽 JAVA GUI(Graphic User Interface)란? AWT 컴포넌트? Swing 컴포넌트?
29강 JAVA 스레드 - 스레드란? - 멀티스레드 문법 - synchronized Lecturer Kim Myoung-Ho
Java의 정석 제 5 장 배 열 Java 정석 남궁성 강의 의
Go Lang 리뷰 이동은.
HTTP 프로토콜의 요청과 응답 동작을 이해한다. 서블릿 및 JSP 를 알아보고 역할을 이해한다.
LIT-GenAppSetup ※ Texting+ 클라이언트 프로그램은 제품 인증을 받은 제품입니다.
Lesson 2. 기본 데이터형.
Adobe 제품 다운로드 및 설치 방법 안내 Adobe Creative Cloud Adobe License 권한을 받으신 분
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
27강 JAVA Collections - II - Map계열 컬렉션 클래스 살펴보기 - Set계열 컬렉션 클래스 살펴보기
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
LabVIEW WiznTec 주임 박명대 1.
ARM Development Suite v1.2
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
5강. 배열 배열이란? 배열의 문법 변수와 같이 이해하는 배열의 메모리 구조의 이해 레퍼런스의 이해 다차원 배열
9강. 클래스 실전 학사 관리 프로그램 만들기 프로그래밍이란 결국 데이터를 효율적으로 관리하기 위한 공구
CHAP 21. 전화, SMS, 주소록.
네트워크 환경 구축과 이미지 전송 호스트/타겟 통신 직렬 통신을 이용한 이미지 전송 수퍼 데몬 BOOTP 환경 구축
Canary value 스택 가드(Stack Guard).
( Windows Service Application Debugging )
디버깅 관련 옵션 실습해보기 발표 : 2008년 5월 19일 2분반 정 훈 승
수동 설치시는 설치 방법 1. 두번에 설치 CD 속에 fscommand 폴더 밑에 Osstem 이라는 폴더를
7주차: Functions and Arrays
함수, 모듈.
발표자 : 이지연 Programming Systems Lab.
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
9 브라우저 객체 모델.
Android -Data Base 윤수진 GyeongSang Univ. IT 1.
엔코더 프로그램 설명 // 쓰레드를 사용하기 때문에 변수와 핸들을 전역변수로 지정 HANDLE hDevice;
1장 C 언어의 개요 C 언어의 역사와 기원 C 언어의 특징 프로그램 과정 C 프로그램 구조 C 프로그램 예제.
CCIT 네트워크 발표 정보보호학과 평문 사이트와 SSL 사이트, SSL strip과 데이터 변조를 이용한 로그인 취약점
Java의 정석 제 8 장 예외처리 (Exception handling) Java 정석 남궁성 강의
CODE INJECTION 시스템B 김한슬.
Assembly 05 방호남 07 반지훈 09 박상욱.
C++ Espresso 제15장 STL 알고리즘.
6 객체.
CCISS 어레이 형식 centos7 설치방법
Chapter 11. 문서 인쇄 및 파일 형식.
SPL-Duino 블록 편집기 이용하기 전류센서 블록 만들기 SPL-Duino 블록 편집기를 실행합니다.
20 XMLHttpRequest.
Presentation transcript:

HandMade Native API Decomplie 안녕하세요 이번에 native API decompile이라는 주제를 가지고 같이 얘기 해볼 유정빈 이라고합니다 Decompile이라는 게 뭔지 아시는 분들이라면 왜 제가 주제에 ‘서handmade 라는 단어를 덧붙엿는지 아실거에요 간단한 내용설명과 더불어서 같이 한땀한땀 api 를 분석해보려 합니다(사실 ppt 만들기 시작하면서 이 주제로 왜햇는지 후회햇죠;) 주어진 시간이 생각보다 얼마 되지않아 완벽한 api 분석은 할수 없을것 같고, api 에서 제공하는 함수 두개정도를 같이 살펴보고, 이번 강연을 마치도록 하겟습니다 symnoisy@3c1c http://symnoisy.tistory.com mupin@hanmail.net

유정빈 Symnoisy.tistory.com 3c1c.tistory.com 시스템 해킹 리버싱 현 KSIA 연합원 그러면 일단 간단히 제소개를 하고 시작하도록 하죠. 앞에서도 이야기 했지만, 제 이름은 유정빈입니다 시스템해킹과 리버싱쪽으로 공부하고있고, 현재 3c1c라는 두명밖에 안되는 팀에서 팀장을 맡고있습니다 현 ksia 연합원 이기도 합니다. 발표를 들으시다가 궁금한점은 끝나고 물어봐주시고 그외의 물어볼것들은 제블로그나 페이스북을 통해 물어봐주세요

API? Native API? System call mechanism INDEX. 자 그러면 본격적으로 진행해 보도록 하죠. 같이 디컴파일을 하기전에 디컴파일이 뭔지, api는 또뭔지 native api는 뭔지 간단하게 설명을 하고 진행하도록 하겟습니다 제 생각에는 아마 디컴파일을 하기시작하면 반이상이 잠들거라 예상합니다 ㅎㅎ System call mechanism

Decompiler & decompile INDEX. Compiler & compile Decompiler & decompile Native API Decompile

1 API? Application programming Interface . Application programming Interface 운영체제가 어플리케이션과 통신을 위해서 제공하는 함수의 모음 자 그러면 API는 뭘까요? API 코딩을 한번이라도 해보신 분들이라면 한번정도는 들어봣을 법한 그런 단어입니다. API란 application programming interface의 약자입니다. 간단하게 얘기를 해보면, 우리가 OS 라 부르는 운영체제와 프로그램이 소통을 하기위해서, 운영체제가 제공해주는 함수의 모음이라고 생각하면 됩니다. 반대의 개념으로는 콜백 함수라는게 있는데, 이것은 우리가 짜놓은 함수가 반대로 운영체제에게 함수를 제공해주는 것이죠. 간단하죠?

1 API? WIn32 interface DLL과 컴포넌트 와의 관계 . API를 얘기하면 당연히 DLL 얘기도 나올수밖에 없어요 왜냐하면 DLL안에 API가 선언이 되어있기 때문이죠 dll 이란 Dynamic Link Library의 약자입니다. 프로그램 자체에는 포함 되지않고,개별적인 파일로 메모리상에 로드가 되게됩니다. 이렇게되면, 특정 메모리영역에 고정적으로 위치해 있기 떄문에, 프로그램에서는 그것을 그냥끌어쓰기만 하면되는 상황이 됩니다. 그렇기 떄문에 프로그램 전체를 패치하지 않더라도, 이 dll 만 건드려주면 모든 부분을 패치해줄수 있는거지요

2 Native API? WIn32 interface DLL과 컴포넌트 와의 관계 . 이어서 각 DLL별 특징을 한번 살펴보죠. Kernel32.dll 모듈안에 구현되어있는 kernel api의 경우에는 GUI와 관련되지않은 파일 I/O, 메모리관리, 객체관리 , 프로세스와 스레드 관리등을 제공합니다 . 이부분에 대한 실질적인 처리는 NTDLL에서 처리를 해주고, 커널단으로 넘어가는 식입니다. 그렇기 떄문에, kernel API를 호출해주면, 내부적으로 ntdll 이 호출이되죠. 그런데 kernel API와 ntdll 이후로 처리되는 부분은 커널 모드 부분인데 유저모드에서 그부분을 직접적으로 이동할수 있게 된다면, 보안적인 문제가 생기게 됩니다.쉽게 생각하면 root 부분의 권한인데 유저모드권한에서 침범하게되는거죠 . 그래서 이런 문제를 해결하기 위해서 시스템 콜 메커니즘이라는걸 이용하죠. 이내용은 바로 다음 페이지에서 살펴보도록 하겟습니다 GDI API의 경우에는 비트맵 이미지에 관련된 API고 ,USER API의 경우에는 윈도우창관리 ,메뉴, 대화상자같은 하이레벨 GUI 관련 인터페이스를 제공해줍니다. 내부적으로 USER API는GUI 객체를 그릴때 GDI를호출하게 됩니다.

2 System call mechanism 2E!2E!2E!2E! . 유저모드에서 커널모드를 호출하기 위한 방법(주로 App이 OS API를 호출할때 자주 발생) KiSystemService, KiServiceTable SYSENTER 2E!2E!2E!2E! 그래서 systemcallmechanism이란 위에 써져있듯이 유저모드에서 커널모드를 호출하기 위한방법입니다. 이 메커니즘은 유저 모드와 커널모드 사이에, 특권 모드라는 모드를 추가해주는 겁니다. 그렇게 된다면, 유저모드에서 커널모드로 넘어갈때, 커널모드에게 유저모드가 커널모드를 사용하기를 원한다! 라는 메시지를 전송해주는 것과 같습니다. 윈도우 2000 버전 이하에서는 인터럽트 2e를 사용햇습니다. 이는 IDT를 이용해서 해당 인터럽트 핸들러를 호출하게 됩니다. 참고로, 2e 라는 인터럽트는 인터럽트 디스크립터 테이블안에서 Kisystemservice라는 NTOSKRNL 내부의 커널 서비스 함수를 가리킵니다. 이는 서비스번호와 스택포인터가 유효한지 확인하고나서, 요청된 커널 함수를 호출해 주게됩니다. 실질적인 커널 함수 호출부분은 다양한 커널 서비스 함수 주소들을 담고있는 KiServiceTable안에서 처리해줍니다. KiSystemService의 경우에는 KiServiceTable로 인덱스를 전달해주는 역할을 해줍니다

3 Native API? 메모리 관리자,I/O 시스템,객체관리자,프로세스와 스레드에 직접접근할 수 있는 인터페이스 제공 . 메모리 관리자,I/O 시스템,객체관리자,프로세스와 스레드에 직접접근할 수 있는 인터페이스 제공 EX)NtCreateFIle(), ZwCreateFile() Native api는 앞서 설명한 kernel32.dll 아래에있는 실질적인 명령들을 처리해주는 ntdll 아래에 선언되어있습니다. 그렇기 때문에 아까말햇던 .kernel32 dll과 비슷하게 메모리관리, i/o 시스템 객체관리 프로세스와 스레드에 직접접근할 수 있는 인터페이스를 제공해주게 되죠 .또한 실질적인 유저모드에 대한 처리는 이부분에서 하기 때문에 커널과 가장 직접적인 인터페이스라고 할 수 있습니다.가장직접적인 반면, 인텔사는 native api 부분을 문서화 하지않앗습니다 왜냐하면 이전버전들이 너무 느리게 사라져갔기때문이죠. 하위 윈도우 버전들과의 호환성을 위해서 문서화를 하지 않았습니다 그렇기 때문에, 우리가 실질적으로 이부분에 선언되어있는 api를 사용하려면, 인터넷을 뒤지거나 혼자 분석해서 사용해야 하는 상황이 발생합니다 그렇기 때문에 이런 주제를 가지고 한번 얘기해볼 필요가 있는거죠.아래에있는 것들은 네이티브 api의 함수들인데요. 네이티브 API의 경우 api이름앞에 nt 라던가 zw라는 접두사가 붙게 됩니다. Nt의 경우 api를 실질적으로 구현하는 함수이고, Zw의 경우 시스템콜 메커니즘이 실행되는 함수라는 것을 알아두면좋을것 같습니다 NT~~~~~ :API 를 실질적으로 구현하는 함수 ZW~~~~~~: 시스템 콜 메커니즘이 수행되는 함수 시스템콜 메커니즘을 통해서 커널모드 API를 호출하는 이유: 호출되는 API를 커널모드에서 호출한다는 것을 알려주기 위해서임 ~>유저모드에서 커널메모리 주소를 전달함으로써 얻을수 있는 시스템 corruption 방지

4 Compiler & Compile 목적코드 C (기계어코드) Compiler . 목적코드 (기계어코드) Compiler C 그러면 잠깐 쉬어갈겸 간단한 내용들을 살펴보겠습니다 우선은 컴파일러 부분인데요. 저도 아직 컴파일러 부분을 깊숙히 공부해보지는 않았지만,

+) Disassem . 어셈블리 언어 Disassem. 목적코드 실행 바이너리 –> 어셈블러

5 Decompiler & Decompile . Decompile. 고급언어 Ex)C 실행 바이너리

문서화 되지 않은(native) API를 찾아보자` 전제 :) 리얼 극한의 상황, IDA 안깔려있고, 인터넷에서 문서 또한 찾을수 없다 가정. 우리에게 주어진건 해당 API에서 함수 일부를 끌어와서 사용하는 프로그램 달랑 하나 이번 발표의 main: 문서화 되지 않은(native) API를 찾아보자` 리얼 극한의 상황 아이다도 안깔려있고,인터넷에서 문서또한 찾을수없다 가정하며, 우리에게 주어진건 해당 api에서 사용하는

6 Native API decompile Ntdll!Generic Table RTL 함수(RunTime Library) . Ntdll!Generic Table RTL 함수(RunTime Library) OS와 상호작용 없이 단순히 문자열이나 데이터 처리와 같은 일상적으로 요구되는 기능을 제공하는 함수

6 Native API decompile .

6 Native API decompile API를 끄집어 낸 다음 API의 이름들을 보고 대충 기능들을 유추해본다 . API를 끄집어 낸 다음 API의 이름들을 보고 대충 기능들을 유추해본다 기능들을 유추해보고 맨땅에 헤딩할때 분석해봐야할 가장 좋은 출발점은 ‘데이터 구조체’부분

그렇다면, 가장 처음 접근해야 할 API는 무엇인가? 그렇다면 이제부터 분석 ㄱㄱ

6 Native API decompile RtlInitializeGenericTable .

6 Native API decompile RtlInitializeGenericTable .

6 Native API decompile Offset18(decimal 24, 7th)=2nd param value EAX= 1st parameter ECX =2nd parameter EDX=0 6 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; UnknownStruct->Memb8= Param5; 스택이 올라가는 방법(높은주소에서 낮은주소, 아니면 낮은주소에서 높은주소 스택은 높은주소에서 낮은주소, 힙은 낮은주소에서 높은주소) , calling convention, intel 문법은 오른쪽에서 왼쪽 또는 왼쪽에서 오른쪽인지 짚어주기 1)Parameter 개수를 찾고 ,지역변수가 뭐가있나 찾아봄 LEA 명령- > 메모리 접근이 아닌 주소를 계산하기 위해서 사용 두번째 포인터로 세개의 포인터 모두 초기화됨 = 각 멤버는 세 포인터 그룹에 대한 포인터

6 Native API decompile Struct TABLE { UNKNOWN Member1; . 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; }

6 Native API decompile RtlInitializeGenericTable .

6 Native API decompile RtlGetElementGenericTable . [summary] 루트 데이터 구조체 안에는 offset+4부터 시작해서 세개의 포인터 그룹이 존재한다 이 포인터들은 다른 세 포인터 그룹을 가리키고 처음에는 자신들을 가리키게 초기화되어 있다.(가정)이는 테이블에 엔트리가 차면 변경 RtlGetElementGenerticTable 함수는 이 포인터중 4번째 파라미터값에 12를 더해서 반환. 12는 세포인터의 전체 크기와 동일 테이블 데이터 구조체에 대한 포인터를 사용하고, 테이블에 대한 index 번호를 사용한다 도출해 낼수 있는 결론: Index 번호와 테이블 구조체에 대한 포인터를 사용한다. 테이블의 엔트리를 반환 값으로 반환한다(가정) 12를 더함으로써 헤더 부분이 아닌 데이터 부분을 반환한다. Offset + 0x10(5th Parameter) =>세번째 포인터인 Offset+C가 가리키는 인덱스 ( 7C992501 주소의 비교문) Offset +C(4th Parameter) => 메모리를 가리키는 포인터 (7C992554 주소의 ADD EAX(4th Parameter에 0C를 더해줌) ECX =1st parameter EDX=6th parameter EAX=4th parameter ESI=5th parameter EDI= 2nd parameter if(Param2 == 0xffffffff) return 0; AdjustedIndexNumber(EBX) =IndexNumber(EDI)+1 if( IndexNumber== 0xffffffff||(AdjustedIndexNumber >6th parameter) return 0; Interleaved코드 : 이부분은 상호 의존적인 명령쌍을 효과적으로 처리하기 위해서 코드위치를 변경한 것이다. 즉 CPU가 먼저 어떤 명령을 실행하기전에 먼저 실행해야 하는명령이 있을때 그 명령을 자연스럽게 먼저 실행하도록 명령위치를 배치한것이다. 간단하게 얘기하면 고수준의 병렬실행이 가능하게해줌 LEA EBX,[EDI+1] 로인해, 2번째 파라미터는 인덱스 번호라는 것을 유추 (Jmp above 명령과 함꼐) AdjustedIndexNumber라는 별칭을 또 따로준 이유는 EBX레지스터를 계속 사용하기 떄문임

6 Native API decompile RtlGetElementGenericTable . 헬 게이트 Open .. 애도요

(세번째 포인터(memb4,EAX)가 가리키는인덱스 6 Native API decompile RtlGetElementGenericTable(로직 이해) ECX =1st parameter EDX=6th parameter EAX=4th parameter (메모리를 가리키는 포인터) ESI=5th parameter (세번째 포인터(memb4,EAX)가 가리키는인덱스 EDI= 2nd parameter EBX = Table Index 값 LOOP1 :) 각 엔트리의 offset +4값을 취하면서 낮은 인덱스 방향 4th parameter: loop 돌면서 찾아낸 엔트리 포인터 5th parameter:해당 엔트리에 대한 인덱스 . 오잉? 일단 보류 빼기연산=비교연산 ESI-EBX=0 or ESI =EBX ESI-EBX= 검색 전체 개수 LOOP ESI !=EBX Case: ESI>EBX Jg , JL = 부호있는값 JA, JB = 부호없는값

6 Native API decompile RtlGetElementGenericTable(로직 이해) ECX =1st parameter EDX=6th parameter EAX=4th parameter (result 가리키는 포인터) ESI=5th parameter (result 엔트리 가리키는인덱스 EDI= 2nd parameter EBX = Table Index 값 . EDX= EDX-(EBX)Table Index+1 EDI=EDI(=EBX)TableIndex-ESI EDX(6th Parameter)=리스트의 끝 ~찾고자하는 엔트리 인덱스 까지의 거리 EDI(2nd Parameter)=찾고자하는 엔트리 인덱스 ~마지막으로 찾은 엔트리 인덱스 까지의 거리 (=마지막인덱스) ESI< EBX (==인경우는 앞에서 윗줄에서 이미처리)

6 Native API decompile RtlGetElementGenericTable(로직 이해) ECX =1st parameter EDX=6th parameter (처음~끝 인덱스 거리) EAX=4th parameter (메모리를 가리키는 포인터) ESI=5th parameter (세번째 포인터(memb4)가 가리키는인덱스 EDI= 2nd parameter (마지막Index) EBX = Table Index 값 . EDX(6th Parameter)=처음부터 끝까지 엔트리 인덱스의 거리 EDI(2nd Parameter)=찾고자하는 엔트리 인덱스 ~마지막으로 찾은 엔트리 인덱스 까지의 거리 (=마지막인덱스)

(세번째 포인터(memb4)가 가리키는인덱스 6 ECX =1st parameter EDX=6th parameter EAX=4th parameter (메모리를 가리키는 포인터) ESI=5th parameter (세번째 포인터(memb4)가 가리키는인덱스 EDI= 2nd parameter EBX = Table Index 값 Native API decompile RtlGetElementGenericTable (로직 이해) .

6 Native API decompile RtlGetElementGenericTable Struct TABLE . Struct TABLE { PVOID UnKnown1; LIST_ENTRY *LLHead; LIST_ENTRY *SomeEntry; LIST_ENTRY *LastElementFound; ULONG LastElementIndex; ULONG NumberOfElements; ULONG Unknown1; ULONG Unknown2; ULONG Unknown3; ULONG Unknown4; }

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; }

6 Native API decompile RtlGetElementGenericTable else { . else { ULONG ElementsToGo = AdjustedElementToGet; ElementFound=(LIST_ENTRY*) &Table->LLHead; while(ElementsToGo--) ElementFound = ElementFound ->Flink; } ULONG ElementsToLastFound=AdjustedElementToGet – LastIndexFound; ULONG ElementsToEnd = TotalElementCount – AdjustedElementToGet +1; if (ElementsToLastFound <= ElementsToEnd) while(ElementsToLastFound -- ) ElementFound = ElementFound->Flink;

6 Native API decompile RtlGetElementGenericTable else { . else { ElementFound = (LIST_ENTRY *)&Table->LLHead; while(ElementsToEnd--) ElementFound = ElementFound->Blink; } Table->LastElementFound= ElementFound; Talbe->LastElementIndex = AdjustedElementToGet; return (PVOID) ((PULONG)ElementFound +3);

결론: 디컴파일은 장인 정신을 요구한다 (하지만 꼭 한번은 해봐야 한다) 디컴파일러를 감사히 여기며 쓰자`

결론: 디컴파일은 장인 정신을 요구한다 (하지만 꼭 한번은 해봐야 한다) (이거로 발표는 하지말자 ;) 디컴파일러를 감사히 여기며 쓰자` (하지만 뭉개질때는 내가 분석해야한다)

THANK YOU! Q&A symnoisy.tistory.com facebook.com/jungbin.yu