기본 콘텐츠로 건너뛰기

라벨이 ReverseEngineering인 게시물 표시

switch-case-default-2

switch-case-default-2 조건이 많은 switch 문 source # include <stdio.h> void f ( int a ) { switch ( a ) { case 0 : printf ( "zero\n" ) ; break ; case 1 : printf ( "one\n" ) ; break ; case 2 : printf ( "two\n" ) ; break ; case 3 : printf ( "three\n" ) ; break ; case 4 : printf ( "four\n" ) ; break ; default : printf ( "something unknown\n" ) ; break ; } } int main ( ) { f ( 2 ) ; } x86 MSVC $SG5332 DB 'zero', 0aH, 00H $SG5334 DB 'one', 0aH, 00H $SG5336 DB 'two', 0aH, 00H $SG5338 DB 'three', 0aH, 00H $SG5340 DB 'four', 0aH, 00H $SG5342 DB 'something unknown', 0aH, 00H EXTRN ___acrt_iob_func:PROC EXTRN ___stdio_common_vfprintf:PROC _main PROC push OFFSET $SG5336 call _printf a

switch-case-default

switch-case-default switch()/case/default source # include <stdio.h> void f ( int a ) { switch ( a ) { case 0 : printf ( "zero\n" ) ; break ; case 1 : printf ( "one\n" ) ; break ; case 2 : printf ( "two\n" ) ; break ; default : printf ( "something unknown\n" ) ; break ; } } int main ( ) { f ( 2 ) ; } x86 MSVC $SG5332 DB 'zero', 0aH, 00H $SG5334 DB 'one', 0aH, 00H $SG5336 DB 'two', 0aH, 00H $SG5338 DB 'something unknown', 0aH, 00H EXTRN ___acrt_iob_func:PROC EXTRN ___stdio_common_vfprintf:PROC _main PROC push ebp mov ebp, esp push 2 call ?f@@YAXH@Z add esp, 4 xor eax, eax pop ebp ret 0 _main ENDP tv64 = -4 ; size = 4 _a$ = 8

64bit-passing-param

64bit-passing-param 64 비트 인자 전달 방식 source code # include <stdio.h> int main ( ) { printf ( "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d; i=%d" , \ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) ; return 0 ; } 처음 4개의 인자는 RCX, RDX, R8, R9 레지스터를 이용하여 전달하고 나머지 인자는 스택을 통해서 전달하는 데, 컴파일러 별 스택 활용 방식에 차이점이 있는 것을 확인할 수 있다. 효율성을 위해 값이 4바이트로 표현 가능한 경우 x86 환경에서 사용되던 exx 레지스터를 활용한다. MSVC 32bit 환경에서 컴파일 시 인자 전달을 위해 PUSH/POP을 사용했던 것과는 대조적으로 MOV를 이용하여 값을 직접 삽입하는 것을 볼 수 있다. $SG4866 DB 'a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d; i=%d', 00H EXTRN __acrt_iob_func:PROC EXTRN __stdio_common_vfprintf:PROC main PROC sub rsp, 88 ; 00000058H mov DWORD PTR [rsp+72], 9 mov DWORD PTR [rsp+64], 8 mov DWORD PTR [rsp+56], 7 mov DWORD PTR [rsp+48], 6 mov DWORD PTR [rsp+40], 5 mov DWORD PTR [rsp+32], 4 mov r9d, 3

Defferences-in-param-MSVC-GCC

Defferences-in-param-MSVC-GCC MSVC와 GCC의 인자 스택 저장 방식 차이점 source code # include <stdio.h> int main ( ) { printf ( "a=%d; b=%d; c=%d" , 1 , 2 , 3 ) ; return 0 ; } MSVC와 GCC가 생성한 코드에서 인자를 스택에 저장하는 방식에 차이점을 보이는 데, GCC는 PUSH/POP을 사용하지 않고 직접 스택에 접근하여 처리하는 것을 볼 수 있다. MSVC push ebp mov ebp, esp push 3 push 2 push 1 push OFFSET $SG5328 call _printf add esp, 16 ; 00000010H xor eax, eax pop ebp ret 0 GCC push ebp mov ebp, esp and esp, -16 sub esp, 16 call ___main mov DWORD PTR [esp+12], 3 mov DWORD PTR [esp+8], 2 mov DWORD PTR [esp+4], 1 mov DWORD PTR [esp], OFFSET FLAT:LC0 call _printf mov eax, 0 leave ret

IDAPython-simply-DataRef

IDAPython 데이터 참조 코드에 색상 설정 코드 “What” 문자열 위치 확인 후 해당 주소를 참조하는 코드에 빨간색을 설정하는 코드 findStr = "What" # 검색할 문자열 startPoint = MinEA ( ) # 최소 주소 endPoint = MaxEA ( ) # 최대 주소 while startPoint < endPoint : # 최대 주소를 넘지 않을 때 까지 "startPoint" 증가시키며 반복 수행 startPoint = idc . FindText ( startPoint , SEARCH_DOWN | SEARCH_NEXT , 0 , 0 , findStr ) # 문자열 검색 if startPoint == idc . BADADDR : break # 가능한 주소가 아니라면 while문 종료 elif '.rdata' == idc . SegName ( startPoint ) : print "Target : " , hex ( startPoint ) , idc . GetDisasm ( startPoint ) # 문자열 위치 정보 출력 for refAddr in DataRefsTo ( startPoint ) : print "Ref : " , hex ( refAddr ) , idc . GetDisasm ( refAddr ) # 참조 위치 정보 출력 idc . SetColor ( refAddr , CIC_ITEM , 0x2020c0 ) # red color # 참조 위치 빨간색 설정 startPoint = idc . NextHead ( startPoint ) # 검색 진행을 위해 "startPoint"에 다음 instruction 설정

IDAPython-simply-patching

IDAPython을 이용한 데이터 패칭 _printf 함수 인자 값 전달 전 EAX 레지스터에 저장된 데이터 주소를 확인하여 해당 주소에 데이터를 xor 패치 후 _printf 함수를 호출하는 간단한 IDAPython 코드이다. def DecodeKey (eax) : for n in range( 0 , 5 ): print "target: " , chr(Byte(eax + n)) # 수정될 문자 PatchByte(eax + n, Byte(eax + n)^ 0x33 ) # xor 연산 print "patch: " , chr(Byte(eax + n)) # 수정 후 결과 def BreakManager (startPoint, targetPoint) : AddBpt(startPoint) # 패치 수행할 위치 afterFunc = idc.NextHead(targetPoint) AddBpt(afterFunc) # _printf 수행 후 위치 findCode = "89 44 24 04" # mov [esp+4], eax targetFunc = "_printf" # 패치한 결과를 전달할 목표 함수 startPoint = MinEA() while True : startPoint = idc.FindBinary(startPoint, SEARCH_DOWN|SEARCH_NEXT, findCode) # 코드 검색 if startPoint == idc.BADADDR: break else : targetPoint = startPoint for ni in range( 0 , 2 ): targetPoint = idc.NextHead(targetPoint) if targetFunc == id

IDAPython-basic-code-snippet

IDAPython 시작하기 많이 사용되는 기본 구문 바이트 : idc.Byte(ea) 워드 : idc.Word(ea) 더블 워드 : idc.Dword(ea) 쿼드 워드 : idc.Qword(ea) Float : idc.GetFloat(ea) Double : idc.GetDouble(ea) 현재 커서 위치 읽어오기 : ea = idc.ScreenEA() 어셈블리 코드 읽어오기 : idc.GetDIsasm(ea) 명령어 읽어오기 : idc.GetMnem(ea) 인자 읽어오기 : idc.GetOpnd(ea, n) 인자 형식 읽어오기 : idc.GetOpType(ea, n) 유효 주소 확인 : if BADADDR != here(): 섹션 출력하기 : for seg in Segments(): print idc.SegName(seg), idc.SegStart(seg), idc.SegEnd(seg) 함수 목록 출력하기 for fun in Functions(): print hex(func), idc.GetFunctionName(func) 사용 가능한 함수 목록 확인하기 ea = ScreenEA() func = idaapi.get_func(ea) print dir(func) 특정 주소가 위치한 함수 영역 구하고 어셈블리 코드 출력하기 ea = ScreenEA() func = idaapi.get_func(ea) start = func.startEA end = func.endEA print "Start: 0x%x, End: 0x%x" % (start, end) while start <= end: print hex(start), idc.GetDisasm(start) start = idc.NextHead(start, end) 코드 상호 참조 찾기 strcpy_addr = idc.LocByName( "st

Windows-Cpp-Exception-via-SEH-1

SEH를 거치는 Windows C++ Exception 윈도우에서 사용되고 있는 Structured Exception Handling(SEH) 는 Exception 관리 시스템이다. 하지만 C++은 자체적으로 Exceptoin을 관리한다. 우리는 예제를 작성하여 WinDbg에서 어떻게 Exception이 관리되는 지 볼 것이다. Structured Exception Handling(SEH) Exception은 프로그램이 실행되는 동안 발생되는 이벤트로 프로그램이 정상적인 제어 흐름을 벗어날 때 야기된다. Exception은 hardware exception 과 software exception 크게 두가지 종류로 분류된다. Hardware exception 은 CPU에 의해 시작된다. 0 나누기 연산이나, 접근 불가 메모리에 접근을 시도하는 명령어 구절을 실행하려고 할 때 발생한다. Sofrware exception 은 응용 프로그램이나 운영체제에 의해 발생한다. 예를 들어, 유효하지 않은 인자에 값을 지정할 때 감지될 수 있다. Structured exception handling 은 hardware와 software exception 양쪽을 처리하는 메커니즘이다. 그리므로 코드는 hardware와 software exception을 동일하게 처리할 수 있다. Structured exception handling 은 디버거, 모든 프로그래밍 언어와 기계를 지원하며 제어를 가능하게 한다. ( Vectored exception handling 은 structured exception handling 이 확장된 개념이다.) 시스템 또한 termination handling 을 지원하므로 보호된 코드 본문이 실행될 때 마다 지정된 종료 코드 블록이 실행되도록 할 수 있다. 종료 코드는 어떻게 보호된 본문을 빠져나갈 것인지에 대한 제어 흐름과 관계없이 실행된다. 예를 들어, termination handler 는 코드의 보호

os-x-windows-kernel-debug

맥에서 윈도우 커널 디버깅 설정하기 1) 타겟 가상 이미지와 디버거 가상 이미지를 준비한다. 2) 타겟 가상 이미지를 구동하여 디버깅 설정을 한다. Windows XP (boot.ini에 디버그 옵션 추가 혹은 기존 항목 복사하여 새 부팅 목록 생성) notepad C:\boot.ini /debug /debugport = com1 /baudrate=115200 Windows 7 bcdedit / copy {current} /d "Debug" msconfig 실행 - 부팅 > "Debug" 항목 선택 > 고급 옵션 > 디버그 항목 선택 후 디버그 포트 "COM1:" 으로 설정 3) 타겟 가상 이미지 전원을 끈 후 시리얼 포트 설정을 한다. - 가상 이미지 폴더에 확장자 VMX 파일 수정 serial0 .present = "TRUE" serial0 .fileType = "pipe" serial0 .fileName = "/private/tmp/com1" serial0 .tryNoRxLoss = "FALSE" serial0 .pipe .endPoint = "server" serial0 .startConnected = "TRUE" serial0 .yieldOnMsrRead = "TRUE" 4) 디버거 가상 이미지 시리얼 포트 설정을 한다. serial0 .present = "TRUE" serial0 .fileType = "pipe" serial0 .fileName = "/private/tmp/com1" serial0 .tryNoRxLoss = "FALSE" serial0 .pipe .endPoint = "

Windbg-windows-kernel-debugging

VMware 윈도우즈 커널 디버깅 환경 설정 윈도우즈 커널 디버깅을 위해 VMware를 활용해보자. 1) 호스트 PC에 Windbg를 설치한다. 검색엔진에서 Windbg 설치 를 검색하면 쉽게 마이크로 소프트 페이지를 찾을 수 있다. 설치 프로그램을 다운받아 설치를 진행한다. 2) 가상 머신의 전원을 끈 후 VM > Settings > Add > Serial Port 를 선택하여 Serial Port를 추가한다. 생성 시 Output to named pipe 옵션을 선택하고 \\.\pipe\[이름 지정] 의 형식으로 Name Pipe를 설정한다. 3) 가상 머신의 전원을 켜 C:\boot.ini 파일을 생성한다. [boot loader] timeout = 30 default =multi (0) disk (0) rdisk (0) partition (1) \ WINDOWS [operating systems] multi ( 0 )disk( 0 )rdisk( 0 )partition( 1 )\ WINDOWS = "Microsoft Windows XP Professional" /fastdetect /debugport= COM1 /baudrate= 115200 4) 호스트 PC에서 명령 프롬프트 실행 후 Windbg 설치 디렉터리로 이동한다. windbg.exe" -k com:port=\\.\pipe\[지정한 이름],baud=115200,pipe,reconnect 명령어를 실행하여 연결을 기다린다. 5) 가상 머신을 재시작하면 호스트 PC의 Windbg에서 연결에 성공한 것을 확인할 수 있다. 6) Break( Ctrl + Break ) 버튼 선택 시 디버그 모드가 동작한다. 7) File > Symbol File Path 를 선택하여 심볼을 설정한다. SRV *c :\symbols *http : //msdl .microsoft.com/download/symbols 웹 심볼