Recent posts

C++ Name Mangling

C++은 함수 오버라이딩, 함수 오버로딩, 연산자 오버로딩, 템플릿 등 복잡한 기능이 있는 언어이다. 그래서 C++의 함수나 타입은 std::allocator<char>::allocator()처럼 특수문자가 들어간 복잡한 이름을 가질 수가 있다.

그래서 컴파일러는 이런 이름들을 _ZNSaIcEC1Ev와 같은 형식으로 이름을 변환해서 사용하는데, 이를 name mangling이라고 부른다.

Name mangling 형식은 컴파일러마다 다르다. 컴파일러에 따라 어떻게 다른 지 궁금하다면 여기를 참고하면 된다.

GCC로 mangling된 이름을 원래대로 돌리고 싶다면 c++filt라는 툴을 쓰면 된다.

$ c++filt -n _ZNSaIcEC1Ev
std::allocator<char>::allocator()

ltrace상에 나오는 mangling된 이름을 원래대로 표시하고 싶다면 -C옵션을 쓰면 된다.

Read more


C# decompilers

개인적으로 ILSpy를 추천.

비교글: http://www.filipekberg.se/2013/02/14/decompiling-dotnet-applications/

1. ILSpy

다운로드: http://ilspy.net/

  • + 무료, 오픈소스
  • + 가벼움
  • + 간단한 설치 (다운받고 압축풀면 끝)
  • - 큰 파일을 열면 잠깐 렉걸림.

2. JustDecompile

다운로드: http://www.telerik.com/products/decompiler.aspx

  • + 무료, 오픈소스
  • + 빠름
  • + 예쁜 UI
  • + 쉬움
  • - 설치하려면 회원가입해야됨
  • - 설치할 때 같이 설치하려는 게 많음

3. dotPeek

다운로드: https://www.jetbrains.com/decompiler/

  • + 무료
  • + 예쁜 UI
  • - 디컴파일 후 쓸데없이 최적화를 함.

4. .NET Reflector

다운로드: http://www.red-gate.com/products/dotnet-development/reflector/

  • + 무료 체험판
  • + IL, C#, VB, F# 등 다양한 언어 지원.
  • + 예쁜 UI
  • - 유료

DEFCON 23 Quals - knockedupd

knockedupd는 23회 DEFCON (2015) 예선 리버싱 문제이다.

x86-64 바이너리와 서버 IP가 주어졌다. 서버 포트는 주어지지 않았다.

1. 둘러보기

C++로 작성되었고, libpcap을 사용한 프로그램이다.

main()에서는 세 가지 일을 한다.

  • --interface--config라는 command line option을 받는다. --interface의 기본값은 en0이고, --config의 기본값은 knockd.conf이다.
  • read_config_402C08를 호출해 config파일을 읽는다
  • start_capture_403FDB를 호출해 패킷 캡쳐를 준비하고 시작한다.

ltrace 결과 pcap handler가 0x40375d라는 것을 알 수 있었다. pcap handler의 위치는 start_capture_403FDB를 리버싱해도 알 수 있다.

$ sudo ltrace ./knockupd --interface eth0
  ...
pcap_dispatch(0x1dd50d0, 0xffffffff, 0x40375d, 0)  = 0
pcap_dispatch(0x1dd50d0, 0xffffffff, 0x40375d, 0)  = 0
pcap_dispatch(0x1dd50d0, 0xffffffff, 0x40375d, 0)  = 0
pcap_dispatch(0x1dd50d0, 0xffffffff, 0x40375d, 0)  = 0
pcap_dispatch(0x1dd50d0, 0xffffffff, 0x40375d, 0)  = 0

Read more


PlaidCTF 2015 - png uncorrupt

We received this PNG file, but we’re a bit concerned the transmission may have not quite been perfect.

1. 헤더 보기

$ file png_uncorrupt.png
png_uncorrupt.png: data

파일 signature에 뭔가 문제가 있다.

문제 파일: 89 50 4E 47 0A 1A 0A 00
바른 파일: 89 50 4E 47 0D 0A 1A 0A

문제에서 “transmission error”를 언급한 걸 보니 이 뒤에도 \r\n(0D 0A)가 \n(0A)로 바뀌어있는 듯 하다.

그래서 모든 \n\r\n으로 바꿨더니 그림이 아예 망가졌다. 0A한 바이트만 보고선 원래 0A였는지 0D 0A가 잘려서 0A가 된 건지 알 수가 없기 때문이었다.

Read more


JFF 3 - AVReversing

AVReversing은 LeaveRet에서 주관한 제 3회 Just For Fun CTF 2015에 나온 AVR 리버싱 문제다.

AVR 리버싱에 대한 전반적인 내용은 아래 글에 나와 있다.

1. Reverse

프로그램 안에 printf와 scanf가 포함되어있기 때문에 printf 안으로 들어가 헤메지 말고 함수 argument를 보고 무슨 함수인지를 알아맞히며 넘어가야 한다.

strcpy, memcpy, memcmp 등은 함수가 작아서 코드를 보면 알 수 있다.

프로그램의 대략적인 구조는 다음과 같다. 코드에서 r25:r24는 w24, r23:r22는 w22… 등으로 표시했다.

void main_FE() {
    // (setup some global variables)
    // (initialize UART console)
    main2_11E();
}

void main2_11E() {
  SP[1:2] = 0x100;            // 0x100: "input:"
  printf_194();
  main3_127();
}

void main3_127() {
  SP[1:2] = 0x107;            // 0x107: "%s"
  SP[3:4] = SP+1;
  scanf_1DD();
  r24 = check_8A(SP+1);
  if (r24 == 0)
    puts_1A6(0x116);          // 0x116: "wrong! :("
  else
    printf_194(0x10A, SP+1);  // 0x10A: "flag is %s\n"
}

void check_8A(char* input) {  // input given through w24, stored at w14
  char table[0x1A];   // SP+1
  char buf[0x1B];     // SP+0x1B, w16

  memcpy(table, 0x13C, 0x1A);
  // 0x13C:
  // 27 F6 76 D6 05 13 A4 85  D3 D7 B6 F7 96 25 74 A3
  // F4 36 75 54 15 76 56 E7  67 02

  if (strlen(input) + 1 != 0x1B) return 0;
  strcpy_18D(buf, input);

  char* w26 = buf;
  char* w20 = buf;
  int w18 = 0;
  while (1) {
    w30 = strlen(input);
    if (w18 >= w30) break;
    *w20 ^= w18;
    w20++;
    w18++;
  }

  int w24 = 0;
  while (1) {
    w20 = strlen(input);
    if (w24 >= w20) break;
    r18 = *w26;
    *w26++ = swap(r18);    // swap nibbles
    w24 ++;
  }

  r24 = memcmp(table, buf, w20);
}

Read more