75

IDAPythonsuspected.tistory.com/attachment/cfile4.uf@998A22445A50DB4734BE7… · IDAPython : IDC 기반으로만들어진Python ... idaapi.Choose2 클래스를사용해GUI

Embed Size (px)

Citation preview

목차

• IDAPython 소개 및 설치

• IDAPython API

• IDAPython 활용

IDAPython 소개 및 설치

IDA Pro : Hex-rays 사의 Disassembler & Debugger

IDC : C언어와 매우 유사한 IDA의 내장 스크립트

IDAPython : IDC 기반으로 만들어진 Python 스크립트

관점

자동화

분석

매크로

IDB에 접근가능한 쿼리

* IDB(IDA Database File)

1. 파이썬 2.7 32bit 설치(https://www.python.org/downloads/)

2. IDA Pro Demo Version 설치(http://out7.hex-rays.com/demo/request)

3. IDAPython 설치(https://github.com/idapython/src)

4. IDAPython 파일 압축 해제5. IDAPython 내부 python 디렉터리를 IDA가 설치된 폴더로 복사6. plugins 폴더 안에 있는 파일들을 IDA Pro의 plugins 폴더로 복사7. python.cfg 파일을 IDA Pro의 cfg 폴더 내로 복사

IDA pro 라이센스가있을경우에는자동으로설치됨으로위과정패스

IDA Pro Version : 6.9.160222IDAPython Version : 1.7.0Python Version : 2.7.6OS : Windows 64bit

실습 버전 :

Alt + F7 : 스크립트파일 가져와 실행

Shift + F2 : 스크립트 명령창 띄움(테스트 코드 작성 시 유용!)

Alt + F9 : 최근 실행한 스크립트 확인

Alt + F7

Shift + F2

IDAPython API

경로 : %IDA_DIR%\\Python 코드 상단에 작성 추천

idc.ScreenEA() : 현재 위치의주소를 리턴

idc.here()

idc.MinEA(address) : 최소 주소를 리턴

idc.MaxEA(address) : 최대 주소를 리턴

• idc.SegName(address) : address에대한 세그먼트 이름을리턴

• idc.SegStart(address) : address에대한 세그먼트 시작 주소를 리턴

• idc.SegEnd(address) : address에대한 세그먼트 마지막주소를 리턴

세그먼트(Segment) : 프로그램에정의된 특정 영역으로 코드, 데이터, 스택이존재

idautils.Functions(start_addr, end_addr) : 함수 목록을 리스트 형태로 리턴(범위지정 가능)

idc.GetFuncName(function_address) : 함수 주소의이름을 리턴

• HotKey를 등록해 첫 번째 인자로 지정한 단축키로원하는 함수 실행

• 함수 이름을 모두 불러와 main, Main, Start, start 값이 포함되어있으면 출력하는 스크립트

idc.GetFunctionAttr(ea, attr) : address의 attr(함수의시작 or 끝 주소) 리턴- attr : FUNCATTR_START(함수의시작), FUNCATTR_END(함수의끝)

idc.GetDisasm(ea) : addres의디스어셈블리를리턴

idc.NextHead(address) : 다음 명령 주소(instruction address)를 리턴

idc.PrevHead(address) : 이전 명령 주소(instruction address)를 리턴

• 특정 함수의 시작부터 끝까지 디스어셈블 코드를 출력하는 스크립트

idc.GetFunctionFlags(address) : address의 플래그 값을 리턴

• FUNC_LIB : 라이브러리 코드를 찾는 데 사용

• FUNC_STATIC : 정적 함수로 컴파일된 함수를 식별하는데 사용

• FUNC_FRAME : 프레임 포인터 push ebp를 사용하는 함수를 식별하는데 사용

• FUNC_BOTTOMBP : FUNC_FRAME과 마찬가지로 프레임 포인터 pop ebp를 추적하는데 사용

• FUNC_THUNK : 다른 함수로 점프하는 간단한 함수인 THUNK를 식별하는데 사용

Flags

• FuncItems(start) : 지정한 함수 주소에서 모든 주소를 리턴

FuncItems의 리턴 값이 iterator 형태이기 때문에 list로 변환하면 쉽게 확인 가능

• GetMnem(address) : address의 레지스터를 리턴

• GetOpnd(ea, n) : addres의 n번째 오퍼랜드 값을 리턴

• GetOpnd 함수는 내부적으로 ua_outop2 함수를 사용 후 tag_remove

함수로 문자열만 추출

• ua_outop2(ea, n) : address의 저수준 문자를 가져옴

• tag_remove(res) : 저수준 문자(res)에서 올바른 문자를 리턴

• GetOpType(ea, n) : addres의 n번째 오퍼랜드 타입을 리턴

• idaapi.cmd.Op1.type : 첫 번째 오퍼랜드 값의 타입

• idaapi.cmd.Op2.type : 두 번째 오퍼랜드 값의 타입

• idaapi.decode_insn(addr) : address를 디코드

• o_void : 명령어에 오퍼랜드가 없으면 0을 리턴

• o_reg : 명령어에 오퍼랜드가 일반 레지스터이면 1을 리턴

• o_mem : 오퍼랜드가 직접적으로 메모리를 참조하면 2를 리턴하며, 주로 DATA를참조하는데 사용

• o_phrase : 오퍼랜드가 인덱스 레지스터로 구성된 경우 3을 리턴

• o_displ : 오퍼랜드가 레지스터와 변위 값(0x18과 같은 정수 값)으로 구성된 경우 4를 리턴

• o_imm : 두 번째 오퍼랜드의 값이 정수와 같은 값이면 5를 리턴

• 모든 함수의 목록을 가져와 레지스터타입(o_reg)의레지스터(call, jmp)를 불러오는스크립트

• Names : IDB 내부에 이름이 있는 주소를 iterator 형태로 리턴

• CodeRefsTo(address, flags) : addres의 상호참조 값을 iterator 형태로 리턴

• IDA에서 함수의 이름을 커서에 대고 단축 키(X)를누르면 상호참조하는주소를 확인할 수 있음

• 특정 검색하고 싶은 함수의 상호참조되는주소를 CodeRefsTo 함수를 통해 검색 후 해당 주소를 빨간색으로 변환하는스크립트

• LocByName(name) : 프로그램바이트인 이름(name)의주소를 리턴(API 주소 찾을 시 유용)

• GetProcAddress가사용되는 곳의 주소를 빨간색으로변환 후 쉽게 식별 가능

• CodeRefsFrom(address, flags) : address가 정의된 곳을 참조

• CodeRefsTo 함수와 반대로 참조하는 값이 아닌 정의된 값을 리턴

• XrefsTo : CodeRefsTo와 기능은 동일하지만 내부에 type 값을 확인 가능

• xref.type : xrefs type value를 출력

• xref.iscode : 참조된 주소가 코드 세그먼트에 존재하면 1 리턴

• FindBinary(ea, flag, searchstr, radix=16) : 시작할 address(ea), flag를 지정해 찾고 싶은 바이너리 값(searchstr)을 검색한다.

• Flag values

Idaapi.GraphViewer 클래스를사용해 그래프 형태로 스크립트개발 가능

idaapi.Choose2 클래스를 사용해 GUI 형태로 스크립트 개발 가능

IDA Bindiff 플러그인(IDB 비교)

IDAPython 활용

dword_xxxx..?????????????

0x401000 함수의 디스어셈코드 데이터 영역 내부의 문자열

• 주소 이름(dword_xxxx)을참조되는데이터 영역 문자열로 변경해주는스크립트

스크립트적용 결과 코드가 가시적으로보여짐

Xshell(ShadowPad 악성코드)

- 네트워크 연결 및 처리를 담당하는 필수 DLL인 nssock2.dll이 변조

nssock2.dll –문제의 1000C6C0 함수

Xshell(ShadowPad 악성코드)

- 네트워크 연결 및 처리를 담당하는 필수 DLL인 nssock2.dll이 변조

nssock2.dll –문제의 1000C6C0 함수

• 1000F718 주소의 XOR 인코딩된 바이너리를덤프하는스크립트

어셈블리 코드 중간에 쓰레기 값(E9)을 추가해서 디스어셈블을 망가뜨리는 트릭

수동으로 undefined(단축키 U) + code(단축키 C)로 변환하는 과정을 수행한 결과, 동일한 코드 발견

반복되는 난독화 과정을 스크립트로 풀기 위해 위 코드에서 사용되는 jump

condition 정보를 모두 수집

• 7x 03 7x 01 E8|E9 형태로 반복되어 경우의 수를 모두 리스트에 작성

• Jump conditio의 hex 값은 70~7F로 확인

0x0부터 순차적으로 jump condition이 존재하는리스트의 각 요소를 검색 후 리스트에저장

JMP(EB)로 강제 치환

스크립트 실행 결과 깔끔한 코드 확인

난독화 코드를 탐지할 수 있는 yara 룰 작성

Yara 룰 테스트 결과, 탐지되는 것을 확인

2. git clone https://github.com/OALabs/FindYara.git

1. pip install yara-python

3. 다운로드 받은 폴더 내부의 FindYara.py 파일을 %IDA_DIR%\plugins 경로에 복사

4. IDA – Edit – Plugins – FindYara 실행

HoyKey(Ctrl-Alt-y) 클릭 후 테스트하고싶은 룰을 선택하면 GUI 창에 주소, 룰 이름, Match 내용, Type 출력

sub_1328E0 : 인코딩된 문자열 디코딩하는 함수unk_1330C0 : 인코딩된 문자열이 존재하는 주소

• sub_1328E0 함수에 대한 상호참조(xrefs to == 단축키 x) 결과, 17개 존재하는 것을 확인

• 디버깅을 통해 어떤 문자열인지 확인 가능하지만 IDA를 통한 정적분석 관점에서 스크립트 작성 필요

인코딩된데이터를 가져와 디코딩 후 주석 및 주소 이름을 변경하는 IDAPython 스크립트 작성

인코딩된 Hex 값을 XOR 디코딩 하는 스크립트

• 문자열 디코딩 함수(0x1328E0)를 사용하는 상호참조 주소와 파라미터 값을 가져와 디코딩 수행

• XrefsTo(address, flags) : address를 상호참조하는 주소를 리스트 형태로 리턴

• MakeComm(address, comment) : address에 comment(주석)을 작성

• MakeName(address, text) : address의 이름을 text(변경하고자 하는 이름)로 변경

• PrevHead(address) : 이전 명령 주소(instruction address)를 리턴

• GetMnem(address) : address의 레지스터를 리턴

• GetOpnd(address, index) : address의 오퍼랜드를 리턴(index로 몇 번째 오퍼랜드 값(0부터 시작)

을 가져올지 결정 가능)

• GetOperandValue(address, index) : addres의 index 오퍼랜드 값의 주소를 리턴

• address의 인코딩된 Byte값을 끝(0일 때까지)까지 순차적으로 가져와 문자열로 변환 후 저장

• Byte(addr) : address의 byte 값을 리턴

• 디코딩된 문자열 17개(API 함수, IP 주소 등)

주소 이름 변경 및 주석 추가

https://www.hex-rays.com/contests/

Hex-Rays에서운영하는 Hex-Rays Plugin Contest

백신업체 어베스트가 오픈소스로공개한 멀웨어 디컴파일러

감사합니다