ASAN - AddressSanitizer




https://github.com/google/sanitizers/wiki/AddressSanitizer


구글의 깃허브에 정의된 ASAN 은 c/c++로 제작된 프로그램에서 버그를 디텍션 해주는 툴 이라고 보면 된다.


따로 설치해서 해야 하는건 없고 컴파일러 Clang 을 설치한뒤 컴파일 할때 -fsanitize=address 옵션만 붙여주도록 하자.


맨 위의 사진은 ASAN을 적용해서 디텍션할 수 있는 버그들의 목록이다.


Sanitizer 시리즈로는 아래와 같은 것들이 있다.


AddressSanitizer (detects addressability issues) - https://github.com/google/sanitizers/wiki/AddressSanitizer

LeakSanitizer (detects memory leaks) - https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer

ThreadSanitizer (detects data races and deadlocks) for C++ and Go - https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual

MemorySanitizer (detects use of uninitialized memory) - https://github.com/google/sanitizers/wiki/MemorySanitizer


사용법은 위 링크에 모두 나와있으니 ASAN과 MSAN만 사용해보도록 하자.


우선 위 기능을 사용하기 위해서 Clang을 설치한다.


sudo apt install clang


*참고 - 기준은 ubuntu 16.04 server *bit LTS 버전이다.


#include <stdlib.h>

// clang -fsanitize=address -O1 -fno-omit-frame-pointer uaf.c -o uaf

int main() {

  char *x = (char*)malloc(10 * sizeof(char*));

  free(x);

  return x[5];

}



위의 예제 코드를 보면 malloc으로 메모리를 할당하고 바로 Free시킨다. 그 이후 Free된 메모리 x를 접근하는데 이는 Free된 메모리를 재 사용하는


Use-After-Free라고 볼 수 있다.


이를 2번째 줄에 있는 커맨드로 컴파일 해보자.


이때 -fsanitize=address 는 ASAN을 사용하겠다는 것이고, -O1은 최적화 (옵션, 아래 페이지에 있어서 그냥 붙임.)


-fno-omit-frame-pointer는 더 좋은 스택트레이스 결과를 보기위해 붙이라고 한다.


각각의 옵션에 대한 정보는 https://github.com/google/sanitizers/wiki/AddressSanitizer#using-addresssanitizer 을 참고하도록 하자.


[sweetchip@ubuntu sanitizer]$ clang -fsanitize=address -O1 -fno-omit-frame-pointer uaf.c -o uaf

[sweetchip@ubuntu sanitizer]$ ./uaf 

=================================================================

==10400==ERROR: AddressSanitizer: heap-use-after-free on address 0x60700000dfb5 at pc 0x0000004e9bbe bp 0x7ffd5c55f6f0 sp 0x7ffd5c55f6e8

READ of size 1 at 0x60700000dfb5 thread T0

    #0 0x4e9bbd  (/home/sweetchip/sanitizer/uaf+0x4e9bbd)

    #1 0x7f031f59582f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

    #2 0x418518  (/home/sweetchip/sanitizer/uaf+0x418518)


0x60700000dfb5 is located 5 bytes inside of 80-byte region [0x60700000dfb0,0x60700000e000)

freed by thread T0 here:

    #0 0x4b84c0  (/home/sweetchip/sanitizer/uaf+0x4b84c0)

    #1 0x4e9b8a  (/home/sweetchip/sanitizer/uaf+0x4e9b8a)

    #2 0x7f031f59582f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)


previously allocated by thread T0 here:

    #0 0x4b8648  (/home/sweetchip/sanitizer/uaf+0x4b8648)

    #1 0x4e9b7f  (/home/sweetchip/sanitizer/uaf+0x4e9b7f)

    #2 0x7f031f59582f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)


SUMMARY: AddressSanitizer: heap-use-after-free (/home/sweetchip/sanitizer/uaf+0x4e9bbd) 

Shadow bytes around the buggy address:

  0x0c0e7fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

=>0x0c0e7fff9bf0: fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd fd fd

  0x0c0e7fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

  0x0c0e7fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

Shadow byte legend (one shadow byte represents 8 application bytes):

  Addressable:           00

  Partially addressable: 01 02 03 04 05 06 07 

  Heap left redzone:       fa

  Heap right redzone:      fb

  Freed heap region:       fd

  Stack left redzone:      f1

  Stack mid redzone:       f2

  Stack right redzone:     f3

  Stack partial redzone:   f4

  Stack after return:      f5

  Stack use after scope:   f8

  Global redzone:          f9

  Global init order:       f6

  Poisoned by user:        f7

  Container overflow:      fc

  Array cookie:            ac

  Intra object redzone:    bb

  ASan internal:           fe

  Left alloca redzone:     ca

  Right alloca redzone:    cb

==10400==ABORTING



그리고 위처럼 디버그 정보가 쭉 출력되고 스택트레이스 정보가 출력된다.





이번엔 MSAN을 사용해보자.


Asan처럼 그냥 옵션만 추가해주면 사용할 수 있기 떄문에 우선 Clang을 설치한 상태여야 한다.


[sweetchip@ubuntu sanitizer]$ cat umr.cc 

#include <stdio.h>

//clang -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g -O2 umr.cc -o umr -fsanitize-memory-track-origins

int main(int argc, char** argv) {

  int a[10];

  a[5] = 0;

  if (a[argc])

    printf("xx\n");

  return 0;

}


이때 -fsanitize=memory 는 MSan을 사용하겠다는 것이고, -fPie -pie는 예제에 붙어있길래 같이 붙였다. 안붙여도 결과만 보는데는 크게 문제가 없는듯 하다.


-fsanitize-memory-track-origins 는 어느 함수에서 메모리를 할당시켰는지 추적할 수 있는 기능이다. 


-fno-omit-frame-pointer 는 ASAN과 같이 스택 트레이서 기능이다.



위 예제 코드를 보면 a배열을 초기화하지 않은 것에 문제가 발생한다.


이 경우 a[argc]로 접근하게 될 경우 여러 문제가 발생할 수 있다.


[sweetchip@ubuntu sanitizer]$ ./umr 5

==10456==WARNING: MemorySanitizer: use-of-uninitialized-value

    #0 0x563e3030d568  (/home/sweetchip/sanitizer/umr+0x87568)

    #1 0x7fd85136082f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

    #2 0x563e3029ff88  (/home/sweetchip/sanitizer/umr+0x19f88)


  Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'

    #0 0x563e3030d430  (/home/sweetchip/sanitizer/umr+0x87430)


SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/sweetchip/sanitizer/umr+0x87568) 

Exiting


[sweetchip@ubuntu sanitizer]$ ./umr 100

==10457==WARNING: MemorySanitizer: use-of-uninitialized-value

    #0 0x56272224f568  (/home/sweetchip/sanitizer/umr+0x87568)

    #1 0x7f0f5626782f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

    #2 0x5627221e1f88  (/home/sweetchip/sanitizer/umr+0x19f88)


  Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'

    #0 0x56272224f430  (/home/sweetchip/sanitizer/umr+0x87430)


SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/sweetchip/sanitizer/umr+0x87568) 

Exiting



MSan 은 위처럼 결과가 나온다.


잘만 사용하면 써먹을 곳이 꽤나 많을듯 하다.

오호..


엄청난 툴이 나왔습니다..!!


@keystone-engine


최근에 멀티 아키텍쳐를 지원하는 opcode generator 를 만들고 있었는데 버그를 만나서 때려쳤는데 얼마 지나지 않아 Keystone 이라고 하는 어셈블러가 나왔네요.


오예


프로젝트의 주소는 https://github.com/keystone-engine/keystone 에서 받고 빌드하실 수 있습니다...!!


공식 홈페이지의 주소는 http://www.keystone-engine.org/ 입니다.


깃에 써있는것을 보면..


Keystone is a lightweight multi-platform, multi-architecture assembler framework. It offers some unparalleled features:

  • Multi-architecture, with support for Arm, Arm64 (AArch64/Armv8), Hexagon, Mips, PowerPC, Sparc, SystemZ & X86 (include 16/32/64bit).
  • Clean/simple/lightweight/intuitive architecture-neutral API.
  • Implemented in C/C++ languages, with bindings for Python, NodeJS, Ruby, Go, Rust & Haskell available.
  • Native support for Windows & *nix (with Mac OSX, Linux, *BSD & Solaris confirmed).
  • Thread-safe by design.
  • Open source - with a dual license.

Keystone is based on LLVM, but it goes much further with a lot more to offer.

Further information is available at http://www.keystone-engine.org



이렇게 써있군요.


오픈소스에 멀티아키텍쳐 및 다양한 언어 지원!! 얼른 써봅시다


Git clone 으로 서버에 받고 나서 빌드 스크립트를 실행하기 전에 아래 Dependency 를 해결해줍시다.


sudo apt-get install cmake


그 이후 keystone의 루트 디렉터리에 build 라는 폴더를 만들고 이동합니다.


그리고 ../make-share.sh 스크립트를 실행해주면 알아서 make를 날려줍니다.


[sweetchip@ubuntu keystone]$ mkdir build

[sweetchip@ubuntu keystone]$ cd build/

[sweetchip@ubuntu build]$ l

[sweetchip@ubuntu build]$ ../make-share.sh 

+ [ -n  ]

+ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DLLVM_TARGETS_TO_BUILD=all -G Unix Makefiles ..

-- The C compiler identification is GNU 5.3.1

-- The CXX compiler identification is GNU 5.3.1

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- The ASM compiler identification is GNU

....

[ 98%] Linking CXX shared library ../lib/libkeystone.so

[ 98%] Built target keystone

Scanning dependencies of target kstool

[ 99%] Building CXX object kstool/CMakeFiles/kstool.dir/kstool.cpp.o

[100%] Linking CXX executable kstool

[100%] Built target kstool



make가 끝났으면 make install로 마무리 해줍니다.


[sweetchip@ubuntu build]$ sudo make install

[ 98%] Built target keystone

[100%] Built target kstool

Install the project...

-- Install configuration: "Release"

-- Installing: /usr/local/lib/pkgconfig/keystone.pc

-- Installing: /usr/local/include/keystone

-- Installing: /usr/local/include/keystone/x86.h

-- Installing: /usr/local/include/keystone/systemz.h

-- Installing: /usr/local/include/keystone/hexagon.h

-- Installing: /usr/local/include/keystone/sparc.h

-- Installing: /usr/local/include/keystone/arm64.h

-- Installing: /usr/local/include/keystone/ppc.h

-- Installing: /usr/local/include/keystone/mips.h

-- Installing: /usr/local/include/keystone/keystone.h

-- Installing: /usr/local/include/keystone/arm.h

-- Installing: /usr/local/lib/libkeystone.so.0

-- Installing: /usr/local/lib/libkeystone.so

-- Installing: /usr/local/bin/kstool

-- Set runtime path of "/usr/local/bin/kstool" to ""



자 이러면 설치 끝!


매우 쉽죠?


간단하게 사용해봅시다.


우선 커맨드라인으로 빠르게 보고싶다면..


[sweetchip@ubuntu build]$ kstool x32 "nop"

nop = [ 90 ]

[sweetchip@ubuntu build]$ kstool x32 "add eax, ebx"

add eax, ebx = [ 01 d8 ]

[sweetchip@ubuntu build]$ kstool arm "mov r1, r1"

mov r1, r1 = [ 01 10 a0 e1 ]



오홍.. 역시 기대한 대로 잘 나오는군요


Kstool v1.0 for Keystone Assembler Engine (www.keystone-engine.org)

By Nguyen Anh Quynh, 2016


Syntax: kstool <arch+mode> <assembly-string> or cat <asmfile> | kstool <arch+mode> 


The following <arch+mode> options are supported:

        x16:       X86 16bit, Intel syntax

        x32:       X86 32bit, Intel syntax

        x64:       X86 64bit, Intel syntax

        x16att:    X86 16bit, AT&T syntax

        x32att:    X86 32bit, AT&T syntax

        x64att:    X86 64bit, AT&T syntax

        x16nasm:   X86 16bit, NASM syntax

        x32nasm:   X86 32bit, NASM syntax

        x64nasm:   X86 64bit, NASM syntax

        arm:       ARM - little endian

        armbe:     ARM - big endian

        thumb:     Thumb - little endian

        thumbbe:   Thumb - big endian

        arm64:     AArch64

        hexagon:   Hexagon

        mips:      Mips - little endian

        mipsbe:    Mips - big endian

        mips64:    Mips64 - little endian

        mips64be:  Mips64 - big endian

        ppc32be:   PowerPC32 - big endian

        ppc64:     PowerPC64 - little endian

        ppc64be:   PowerPC64 - big endian

        sparc:     Sparc - little endian

        sparcbe:   Sparc - big endian

        sparc64:   Sparc64 - little endian

        sparc64be: Sparc64 - big endian

        systemz:   SystemZ (S390x)



위는 지원하는 목록입니다.


[sweetchip@ubuntu python]$ ls

keystone  LICENSE.TXT  Makefile  MANIFEST.in  README.md  sample.py  setup.py

[sweetchip@ubuntu python]$ sudo python setup.py install

running install

running build

running build_py

creating build

...


만약 python에서도 사용하고 싶다면 keystone/bindings/python/ 로 이동후에 설치해줍니다!


[sweetchip@ubuntu python]$ python sample.py 

add eax, ecx = [ 66 01 c8 ]

add eax, ecx = [ 01 c8 ]

add rax, rcx = [ 48 01 c8 ]

add %ecx, %eax = [ 01 c8 ]

add %rcx, %rax = [ 48 01 c8 ]

sub r1, r2, r5 = [ 05 10 42 e0 ]

sub r1, r2, r5 = [ e0 42 10 05 ]

movs r4, #0xf0 = [ f0 24 ]

movs r4, #0xf0 = [ 24 f0 ]

ldr w1, [sp, #0x8] = [ e1 0b 40 b9 ]

v23.w=vavg(v11.w,v2.w):rnd = [ d7 cb e2 1c ]

and $9, $6, $7 = [ 24 48 c7 00 ]

and $9, $6, $7 = [ 00 c7 48 24 ]

and $9, $6, $7 = [ 24 48 c7 00 ]

and $9, $6, $7 = [ 00 c7 48 24 ]

add 1, 2, 3 = [ 7c 22 1a 14 ]

add 1, 2, 3 = [ 14 1a 22 7c ]

add 1, 2, 3 = [ 7c 22 1a 14 ]

add %g1, %g2, %g3 = [ 02 40 00 86 ]

add %g1, %g2, %g3 = [ 86 00 40 02 ]

a %r0, 4095(%r15,%r1) = [ 5a 0f 1f ff ]



설치 후 sample.py를 실행시켜 제대로 작동하는지 확인하니 잘 나오네요.


이제 이걸로 뭘 할까나..






매번 똑같이 오랜만의 포스팅..


요즘은 커널에 대해서 공부하고 있습니다.


아니나 다를까 공부에는 항상 삽질이 따르네요.


VMware의 Workstation과 Vsphere에서 커널디버깅을 시도해보려고 구글링도 해보다가 실패해서 이것저것 삽질하던 도중 드디어 해결하게 되었습니다.


나중에 까먹을까봐 다시 포스팅!


우선 BOB 할때 알렉스에게 받은 Windbg 파일..


아래 file1, file2 둘중 아무거나 받으시면 됩니다. 같은거에요

===============================

file 1


kdbg.7z.001


kdbg.7z.002


kdbg.7z.003


kdbg.7z.004


==============================

file 2


kdbg.zip.001


kdbg.zip.002


kdbg.zip.003


kdbg.zip.004



윈도우 XP에서의 커널 디버깅 환경 세팅

- Windows XP

- VMware Workstation 11


1. 윈도우XP가 깔린 VM이미지의 속성을 들어간다.




2. 위와 같이 설정에 들어갔으면 아래 Add 버튼을 누른다.





그리고 시리얼 포트를 선택하고 Next를 누른다.


다음 화면은 귀찮아서 캡쳐 실패. 그런데 그냥 텍스트로 적어도 무방할 것 같다.


3. Serial Port 설정에서 'Output to named pipe' 선택 후 Next 클릭

4. Named pipe에 '\\.\pipe\name' 식으로 파이프의 이름을 만들어준다. 예를들어서 '\\.\pipe\sweetchip' 도 좋다.

4-1. 그리고 This end is the client. 와 This other end is an application 각각 선택!



그래서 설정을 살펴보면 이렇게 되도록 한다.


체크할 부분은 Use named pipe와 I/O mode이다.


5. 마지막! I/O mode의 Yield CPU on poll을 체크한다.




그러면 VM웨어에서의 세팅을 마쳤다. 이제 XP에서 설정해보자.


6. XP의 시작 - 실행 - msconfin 입력


7. 시스템 구성 유틸리티의 BOOT.INI 탭 선택


8. 하단 고급 옵션 클릭.



9. 그리고 /DEBUG 체크, /DEBUGPORT, /BAUDRATE 체크


10. 각각 설정을 위 사진처럼 설정. (디버그 포트는 COM1번, BAUDRATE는 115200)


Windows XP에서의 설정은 마쳤고 마지막으로 windbg에서 설정을 해야한다.


Windbg의 설정은 공통설정에서 하겠다.


11. 공통으로 이동



윈도우7 에서의 커널 디버깅 환경 세팅

1. 우선 Windows 7에서 설정을 해줘야 한다.

- XP에서와 마찬가지로 시작 - 실행 - msconfig 입력

- 부팅 탭에서 고급옵션 클릭

- 고급 옵션 창에서 디버그, 디버그 포트, 전송속도 체크아래와 같이 설정



2. 그리고 윈도우7의 전원을 끈다.



3. VMware에서 이미지의 속성을 들어간 뒤 하드웨어의 장치를 추가해줘야 한다.

- Virtual Machine Settings에서 Add 클릭

- Serial Port 클릭 후 Next

- Named Pipe에 위와 같이 설정.

- 파이프 이름 설정 - \\.\pipe\name (파이프 이름의 경우는 자유, 위 사진처럼 자유로 설정.)



4. 그리고 I/O mode에서 Yield CPU on poll 체크


5. 공통으로 이동




[공통] Windbg에서 커널 디버깅하기


1. Windbg의 상단탭 File - Kernel Debugging에 들어간다.





2. COM 탭 클릭후 아래 사진처럼 세팅한다.



3. VMware에서 VM 시작을 누르면..


4. 성공




성공이다!. 사진에서는 Windows XP인데 7이면 Windows 7 이라고 나온다





만약 위와 같은 과정으로 설정 해도 실패할 경우 아래를 살펴보세요,


지금까지 위처럼 해도 디버기가 디버거에 안붙길래 도데체 무슨 일이지 하고 있던 차에 무언가 이상한 것을 발견했다.


위의 경우는 Serial Port를 추가하면 이름은 Serial Port이다.


그러나 나의 경우는 Serial Port 2 라고 이름이 생성되었다. 그 말인 즉, 어떤 장치가 이미 시리얼 포트를 쓰고 있던 것이다.


범인은 바로 프린터(Printer)가 COM1를 사용하고 있었고 이 친구 덕분에 위 설정으로는 디버기가 붙지 않게 되었다.


그러므로 VM에서 프린터가 쓸 일이 없다면 COM1 포트를 사용하기 위해서 과감하게 삭제 하고 붙이면 잘 작동 할 것이다.


허무.. 어쨋든 이제야 잘 붙는다 오예!


끝.


안녕하세요.


요즘 학교 6시간 연강에 고통받으랴 회사일 개인연구.. 등등에 고통받고 있느라 블로그를 잘 못하게 되네요..


얼마전에 IOS에 대해서 연구를 하고싶은게 있어서(라고 썻지만 가지고 놀려고..) 아이패드를 구입하게 되었는데 IOS 앱 바이너리를 추출해보고 싶었습니다.


우선 아이패드의 운영체제인 IOS 8 기준으로 앱스토어에서 다운로드 받은 어플리케이션들은 모두 암호화 되어있다고 합니다.


그래서 실행할 경우 언패킹 과정을 거쳐 메모리에 원본 바이너리를 올린 뒤에 실제 프로그램 루틴이 실행 된다고 하는데, 자세한 원리는 아래 링크를 참고해보시면 되겠습니다.


[IOS Tutorial #1] IOS App 암호화 해제하기 (Decrypting IOS App Binary Encryption) On IOS 6.1.3

- http://repo.kr/0x04-ios-penetration-testing/decrypting-ios-app-binary-encryption-on-ios-6-1-3/



자, 이제 앱 원본 바이너리를 추출해 봅시다.


/*

* 이 포스팅은 IOS 연구를 하시는 분들을 위하여 작성된 게시물 입니다.

* 해당 포스팅을 이용하여 불법적으로 상업적인 이득을 취하거나 그 외 법적으로 문제가 발생할 경우 책임은 본인에게 있음을 알려드립니다.

*/


먼저 준비물은 맥북(Mac os가 설치된 컴퓨터), Root 권한을 얻은 아이폰이나 아이패드 등의 IOS가 설치된 기기가 필요합니다.


또한 아래는 IOS 8.1 기준으로 진행한 방법입니다.


우선 바이너리를 추출하고 복호화 하는 방법은 여러가지가 있지만 그 중 대표적인 방법은 실행된 바이너리를 GDB로 붙여서 메모리 덤프를 해서 실행 파일로 만드는 것입니다.


하지만 이 과정도 상당히 귀찮은 면이 많기때문에 stefan esser 라는 외국 짱짱해커분이 만들어두신 dumpdecrypted 로 비교적 쉽게 덤프가 가능합니다.


https://github.com/stefanesser/dumpdecrypted 의 프로젝트를 다운로드 받고 make 명령어로 dylib 파일을 생성합니다.


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump$ git clone git://github.com/stefanesser/dumpdecrypted

Cloning into 'dumpdecrypted'...

remote: Counting objects: 31, done.

remote: Total 31 (delta 0), reused 0 (delta 0), pack-reused 31

Receiving objects: 100% (31/31), 6.50 KiB | 0 bytes/s, done.

Resolving deltas: 100% (15/15), done.

Checking connectivity... done.


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump$ ls

dumpdecrypted


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump$ cd dumpdecrypted/


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump/dumpdecrypted$ ls

Makefile README dumpdecrypted.c


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump/dumpdecrypted$ make

`xcrun --sdk iphoneos --find gcc` -Os -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path` -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -c -o dumpdecrypted.o dumpdecrypted.c

`xcrun --sdk iphoneos --find gcc` -Os -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path` -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -dynamiclib -o dumpdecrypted.dylib dumpdecrypted.o


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump/dumpdecrypted$ ls

Makefile README dumpdecrypted.c dumpdecrypted.dylib dumpdecrypted.o


sweetchip@sweetchipui-MacBook-Pro:~/Desktop/dump/dumpdecrypted$ scp ./dumpdecrypted.dylib root@[192.168.0.44]:/var/root

The authenticity of host '192.168.0.44 (192.168.0.44)' can't be established.

RSA key fingerprint is 7b:dd:df:de:4c:3d:cb:93:04:91:b2:99:88:37:6e:c3.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '192.168.0.44' (RSA) to the list of known hosts.

root@192.168.0.44's password:

dumpdecrypted.dylib 100% 193KB 192.9KB/s 00:00


그리고 만들어진 파일을 scp로 제 아이패드에 복사시킵니다.


그후 아이패드 SSH에 접속합니다.


hyeonseong-won-ui-iPad:~ root# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /private/var/mobile/Containers/Bundle/Application/00000000-0000-0000-0000-000000000000/appname.app/appname mach-o decryption dumper

mach-o decryption dumper


DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.


[ ] detected 32bit ARM binary in memory.

[ ] offset to cryptid found: @0xb9a08(from 0xb9000) = a08

[ ] Found encrypted data at address 00004000 of length 13877248 bytes - type 1.

[ ] Opening /private/var/mobile/Containers/Bundle/Application/00000000-0000-0000-0000-000000000000/appname.app/appname for reading.

[ ] Reading header

[ ] Detecting header type

[ ] Executable is a plain MACH-O image

[ ] Opening appname.decrypted for writing.

[ ] Copying the not encrypted start of the file

[ ] Dumping the decrypted data into the file

[ ] Copying the not encrypted remainder of the file

[ ] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset a08

[ ] Closing original file

[ ] Closing dump file

hyeonseong-won-ui-iPad:~ root# ls

Application Support appname.decrypted Library dumpdecrypted.dylib


/private/var/mobile/Containers/Bundle/Application/ 경로에 보시면 현재 설치된 앱 바이너리들이 있는데 이는 find 명령어 등으로 정확한 위치를 알아내신 뒤,


위와같이 커맨드를 입력합니다. 그러면 자동으로 디크립션된 앱을 통째로 덤프 떠주면서 마지막으론 appname.decrypted 라는 파일을 뱉어냅니다.


그 후 IFunBox 등의 유틸이나 scp 등을 이용하여 프로그램을 추출하시면 복호화된 원본 바이너리를 얻을 수 있습니다.


이 과정으로 GDB를 붙이는 것에 비하여 비교적 간단하게 어플을 가져올 수 있었습니다.


끝!



참고 링크 1 : http://blog.l4ys.tw/2014/01/dump-ios-app-headers.html

참고 링크 2 : https://github.com/stefanesser/dumpdecrypted




얼마전 pydbg로 새로운 Fuzzer를 제작했는데 얼마전에 Python으로 API를 사용하여 디버거를 만들었다가 Access Violation을 제대로 잡지 못하는


참상을 겪었기에 다른분들이 퍼져를 만들때 사용하셨던 pydbg를 이용해서 만들기로 했습니다만 설치부터 문제가 생겨서 설치만 몇시간을 날렸습니다.


하지만 그러다가 곧 검색을 통해서 사막의 오아시스처럼 pydbg를 설치할수 있는 방법을 배포하시는 블로거 분을 발견했고 바로 따라했습니다.


http://ethobis.tistory.com/entry/Python-27-PeiMei-Pydbg-사용방법


[아래 나올 자료도 블로거님의 자료임을 미리 알립니다.]


[또한 이 자료는 Windows XP 기준으로 설명했습니다.]





우선 파이썬 2.7.3을 기준으로 설명하겠습니다. 권장이 2.7.3으로 알고 있어서 다른 버전은 왠지 호환이 안될까봐 2.7.3으로 진행했습니다.


Python 2.7.3 : http://python.org/ftp/python/2.7.3/python-2.7.3rc1.msi [windows]


파이썬을 모두 설치하면 Paimei를 설치해야 합니다.


PaiMei-1.1.win32.exe

[paimei 1.1 - windows]


paimei를 설치하면 다음 파일을 다운로드 받아주세요.


pydasm.pyd


위 파일을 다운로드 받아서 C:\Python27\Lib\site-packages\pydbg 경로에 넣어주세요.


그리고 마지막으로 아래 파일을 받아서 C:\Python27\Lib\ctypes 에 덮어 씌워 주세요.


__init__.py


그리고 이제 Python Idle 을 여시고 import pydbg 를 입력하시고 아무 에러가 안뜨신다면 성공입니다.



끝~!


수고하셨습니다.




결과가 발표나서 이제 write up을 올릴수 잇게 되엇네요.


하.. 대회때 네트워크 문제 덕분에 멘붕하고 번호판 문제떄문에 멘붕하고 저에게 미스크 문제는 맞지 않는다는걸 알게되었던 대회였습니다.


끝나고 나서 문제가 간단하게 풀리는것도 있엇고 풀이 보고 아. 했던 문제도 많았습니다.. -_-;;... 조금만더 할껄 그랬습니다. 쩝쩝





12


7C1083C98704D3ACC3B7DC801939EF14


한개의 바이너리가 주어졌고 매직넘버를 보니 exe 파일이어서 확장자를 exe로 바꾼다음 실행했다.


실행에는 msvcr100.dll 이 필요하다.




print auth key와 print hello가 있다.





아니 이런.. 나쁜 타원님이 키를 가려버렸다.


그렇다면 저 원을 제거하면 되겠다.


라고 생각 했으나 복잡해질것 같아서 그냥 text를 출력시키는 부분을 찾아보려고 했다.


hex 에디터로 뒤져보니 textoutw 가있엇고 xp에서 gdi32.dll의 base addr 과 textoutw의 offset을 더해서 0x77e27eac에 BreakPoint를 설정했다.


[현재는 print auth key를 누른 상태이다.]



역시 함수에 진입한걸 볼수 있다.


Flag : FuCking_virTua1izer





16



3E5037AE7707FC76FCEFBEEB86630562



이번에도 역시 한개의 바이너리가 주어졌다.


매직넘버를 살펴보니 zip 파일이었고 zip으로 바꾸자 trouble.py가 있었다.


그리고 base64로 인코딩 되어있엇다.


키값은 여러번 난독화 되어있엇는데. 처음에 print로 바꿔보고 확인을 하니 난독화가 몇번 정도 되어있던것 같다.




맨처음 exec는 그대로 나둬야 실행이 되고 복호화가 진행되고 등등등 계속 exec를 print로 바꿔주면 실행대신 출력으로 바뀌어서 답이 출력된다.




Flag : i_knew_you_were_trouble





9



61A4DCB5ADD9A1DC057D65BC57DFC70F



역시 바이너리 한개가 주어졌다.


매직넘버를 확인 해보니 zip 이었고 압축을 풀어보니 dll 하나와 exe가 나왔다.


xp에선 돌아가지 않아 windows7에서 분석을 진행했다.


이문제를 대회때 풀지 못햇는데 도데체 왜! 하는데 끝나고 다시 한번 보고 알았다..


프로그램은 간단하게 strcmp로 Nope debugger~!@와 비교하는 프로그램이었는데 아무리 해도 답이 인증이 안됬엇다.


그래서 뭔가.. 관두고 대회끝나고 다시 풀어봤더니 attach를 했더니 lstrcmpa 가 이상한 주소로 바뀌어 있엇다


로딩을 하면 정상적인 strcmp 가 되있고 attach를 하면 이상한 주소로 변경이 되어있엇다.


그렇다면 .. 안티디버깅 기법이다.




현재 디버깅인지 아닌지 판단을 하고 디버깅일경우 0x70으로 변한다.


디버깅중이 아닐경우 0으로 그대로 유지되는 방식으로 디버깅을 판단한다.


만약 디버깅 중일시 그냥 넘기고 디버깅중이 아닐시 istrcmpa의 포인터를 04002110 으로 바꿔버린다.


그래서 아까처럼 attach를 하면 주소가 바뀌어 있엇던 것이다.


[추가 : 다른분의 풀이를 보니 ntglobalflag를 이용한 것이라고 한다.]


그러면 이제 jnz를 nop으로 바꾸든, new origin here로 바꿔도 상관없다 istrcmpa의 포인터만 변경하게 한 다음 main함수로 진입하자.



lstrcmpa 함수 안으로 진입을 하자! [주소는 04002110으로 바뀌어있는 상태이다.]





그리고 4번 xor을 하는걸 볼수 있는데 jnz로 비교를 하는건 그냥 무시하고 따로 xor 시키자.


import sys


f = lambda a: str(hex(a)).replace("0x","").decode("hex")[::-1];


a = (0x00905a4d ^ 0x57E3313F)

b = (0x00000003 ^ 0x68516168)

c = (0x00000004 ^ 0x666E5260)

d = (0x0000ffff ^ 0x0074949E)


print "Flag : " f(a) f(b) f(c) f(d)




Flag : rksWkaQhdRnfakt


간짬뽕은 꿀맛이라고 한다.


저도 동감합니다. 히히



어제 시큐인사이드 문제를 푸는데 갑자기 이 문제가 생각나서 다시한번 풀어보게 되었습니다.


시큐인사이드의 game 문제와 비슷하네요~


Reversing.kr FPS [바이너리는 reversing.kr 에 있습니다.]




문제는 3D 게임 서든@택의 텍스트를 본 따서 만든것 같습니다.


일반 fps게임과 같으며 걸어다니는 고구마들을 모두 제거해야 합니다.


옛날에 풀면서 삽질을좀 했는데 이상한 문자열이 존재 했었습니다.



이 문자열을 보면서 상관이 있나 없나 계속 고민을 하고 고구마들을 모두 쏘고나니 아래와 같이 바뀌었습니다.



축하합니다 답은 Thr3EDPr... 인데 답이 깨진것 같습니다.


다시 상황을 살펴보면 몬스터를 한마리 잡을때마다 1바이트씩 변화가 생기기 시작했습니다.


그렇다면 모든 고구마를 없애버리면 해결되지 않을까 생각을 했고 그 생각 대로라면 의문의 50바이트 문자열을 모두 복호화 시키려면


50마리[?]의 고구마를 모두 없애야 했습니다.



하지만 위 사진에는 2개가 바뀌지 않았고 실제로 세보니 48마리 였습니다.


그래서 생각해 낸것이 흔하게 말하는 벽을 뚫는 '월핵' 이나 복호화 루틴을 알아내서 복호화 시키는 것이었습니다.


저는 복호화 루틴을 알아 내기로 했습니다.


위 의문의 50바이트에 메모리 브레이크 포인트를 설정하고 몬스터를 잡자 아래와 같은 함수에서 멈췄습니다.



위가 바로 복호화 시키는 부분입니다.


BP를 기준으로 몬스터를 죽이면 아래 JG문 바로 아래로 내려가 xor 연산을 시행합니다.


하지만 어느 것과 연산을 하는지는 아직 잘 모르기 때문에 00403427에 BP를 설정하고 CL을 받아오는 메모리 주소를 복사하고


프로그램을 다시 로딩시킨뒤 방금 메모해둔 메모리 주소에 하드웨어 브레이크를 설정했습니다.



그랬더니 아래와 같은 루프에서 멈췄습니다.



이 부분이 의문의 50바이트와 함께 xor 연산을할 배열을 생성하는 부분입니다.


잡다한것 빼고 필요한것만 분석해보면 배열을 생성하는데 0x00~0xc4 까지 0x04 간격으로 배열을 생성합니다 [0, 4, 8, c, ... , c4]



총 정리를 해보면


1. 몬스터를 잡을때마다 한글자씩 복호화가 되는것을 확인

2. 의문의 50바이트와 숫자배열[0x00 ~ 0xc4]과 xor 연산

3. 복호화는 배열순서에 따라서 진행 [ex 의문의50바이트[1]^숫자배열[1]]


이므로 스크립트를 만들어서 따로 복호화 할 것입니다.


의문의 50바이트 - en_data


import array


f = open("en_data","rb")

encrypted = bytearray(f.read())

f.close()


a=array.array('i',(i*4 for i in range(0,0xc4/4 1)))


for i in range(len(a)):

encrypted[i] = encrypted[i] ^ a[i]


print "Flag : " encrypted





Flag : [삭제]


후!


이번 주말은 너무 바빳습니다.


자기소개서를 쓰면서 또 취약점도 분석하고 등등... 너무 할일이 많았던 주말이었습니다.


그러면서 잠시나마 즐거움을 줬던것이 시큐인사이드 ctf였엇는데 틈날때마다 한두시간 들어가서 문제를 풀이 했습니다.


쉬운건 쉬우나 어려운건 어려웠습니다. ㅋㅋ


그중 리버싱 문제 간단한것 2개를 풀이 해 보도록 하겠습니다.





PE_Time


PE_time (1).zip





프로그램을 실행시켜보면 메세지 박스가 뜨고 확인을 누르면 어느 캐릭터가 나오는 프로그램입니다.


exeinfo로 살펴보니 unknown 이라고 떠서 그냥 이뮤니티에 바로 attach 시켰습니다.


문자열 검색을 해보니 C;@R 이 나왔고 그 바로 위에는 sub와 xor 연산이 있는 것이 보이고 getwindowstext가 있는것을 보아 100%라는 것을 확신하고


분석을 시작햇습니다.


간단하게 첫번째 글자를 가져오고 5를 뺀다음 3과 xor 연산을 하고 다시 4를 빼고 3과 xor연산을 하는 것처럼 보였습니다.


처음 답을 얻으려면 다시 거꾸로 진행만 하면 될것같아 스크립트를 작성햇습니다.


b = bytearray("C;@R")


for i in range(1,6):

b[0] ^= 0x3

b[0] = i


for i in range(1,5):

b[1] ^= 0x4

b[1] = i


for i in range(1,4):

b[2] ^= 0x5

b[2] = i


for i in range(1,3):

b[3] ^= 0x6

b[3] = i


print "Flag : " b





Flag : SECU





game


beist_attack_game3.exe



exe 파일 한개가 주어졌습니다.


힌트를 보니 바이트 배열이라고 하는데 왠지 삘이 딱 와서 바로 풀이를 시작했습니다.




사람이 날라 다니며 강력한 총알을 발사하는 슈팅게임입니다.


디버거로 Attach 시키고 한번 메모리덤프를 쭈욱 살펴보던 차에 왠지 수상해 보이는 부분을 발견 했습니다.




바로 이부분 입니다. 왠지 많이 매우 수상해보입니다. 그냥 Feel 입니다. ㅋㅋ


그래서 게임을 좀 하다 보니..


아니!! 이렇게 바뀌어 있었습니다.


저렇게 바뀌는 것은 점수가 20점이 되었을때 연산이 시작됩니다.


그래서 프로그램을 다시 로딩시키고 하드웨어 브레이크를 설정했습니다.



그랬더니 저부분에서 멈춥니다.


예상대로 xor 연산을 하고 있었습니다.


하지만 P!.... 이 부분은 전혀 답처럼 보이지 않았고 다른 연산이 무언가 있을것이 분명해서 IDA로 찾아봤습니다.




IDA로 아까 루프 부분을 찾았습니다.



Hex-ray로 변환시켜 보니 == 20 이 있는것을 보아 역시 20점이 되면 바뀌는것을 확실히 볼수 있었습니다.


그리고 xor 연산을 하는것도 확실히 보이네요!


이부분까지 연산을 한뒤, 불완전한 답이 메모리에 존재하는걸 아까 확인 했고


다른 루틴을 찾아보기 위해서 byte_406450를 하이라이트 시키고 밑으로 내려봤습니다.



오오... 이부분이 확실해 보입니다.


%s 가 있는것을 보아 무언가를 출력하고 각 글자마다 18[int] 를 더하는 것을 볼수 있었습니다.


저렇게 연산한뒤 답을 출력할것 같아 간단한 스크립트를 제작했습니다.


encrypted_data 파일.


b = bytearray(open('encrypted_data', 'rb').read())


data1 = ""


for i in range(len(b)):

b[i] ^= 0x98

for i in range(len(b)):

b[i] = 0x12 # hex(18)


print "Flag : " b






Flag : b315t_15_0ur_3n3my!!


+ Recent posts