Description

Category: Reversing

Source: wargame.kr

Points: 376

Author: Jisoon Park(js00n.park)

Description:

Simple Reverse Engineering Challenge.

Write-up

실행파일이 주어지고, 실행해보면 뭔가 숫자를 입력하고 auth를 해야하는것 같다.

아무거나 넣어보면 wrong password라고 얘기해준다.

decompile을 시도한 후 wrong password 문자열을 찾아본다.

이 문자열을 사용하는 함수를 디컴파일 해보면 대충 아래와 같은 코드를 얻을 수 있다.

//(생략...)

  Time = _time64(0);
  v2 = *((_DWORD *)v1 + 29);
  v3 = (const wchar_t **)((char *)v1 + 116);
  v4 = *(_DWORD *)(v2 - 12);
  if ( ((1 - *(_DWORD *)(v2 - 16 + 12)) | (*(_DWORD *)(v2 - 16 + 8) - v4)) < 0 )
    ((void (__stdcall *)(int))sub_C22420)(v4);
  v5 = _wtoi(*v3);
  if ( _localtime64_s(&Tm, &Time) )
    v6 = 0;
  else
    v6 = Tm.tm_mon + 1;
  if ( 0xFFFCECC9 * v6 + v5 == 0xBADBABE )
  {
    AfxMessageBox(L"congratulations! Authentication key is .....", 0, 0);

//(생략...)

_wtoi() 함수를 이용하는걸 보면 keypad로 입력한 값이 v5에 저장되는것 같다.

if문을 true로 만드려면 v6를 알아야 하는데, v6는 _locatime64_s() 함수의 리턴값과 동작 내용으로 알아낼 수 있을 것 같다.

MS api 페이지를 참조해보면, _locatime64_s() 함수는 시간 데이터를 구조체에 채워주고, 성공하면 0을 리턴한다고 한다. 뭐 이런 시스템 함수가 실패할거 같지는 않고, else 절을 보면 Tm.tm_mon을 이용하는데, 지금이 12월이니 11이 될것 같다.(보통 month 데이터는 0~11로 표현되니까)

v6 = 11 + 1 = 12가 될거고, 이걸로 if 문을 만족시키는 v5를 역산해 보면 0xbd2a152를 얻을 수 있다. 이를 decimal로 변환하여 198353234를 입력하면 keypad 하단의 입력창에서 flag를 얻을 수 있다.

Flag : 1567d027bf68fc0ab316728628e8ed3a45189ef8

그냥 대충 위치만 잡고 디버거에서 if-true branch를 타도록 해도 될거 같았지만 그냥 리버싱 연습하는 의미에서 간단하게나마 코드 분석으로 진행했다.

'writeups > Reversing' 카테고리의 다른 글

Cr4ckZ33C0d3  (0) 2019.11.23
Cheesy  (0) 2019.11.23
flag  (0) 2019.11.23
DLL with notepad  (0) 2019.11.23
baby-re  (0) 2019.11.23

Description

Category: Misc/JPEG

Source: SECCON CTF 2017 Quals.

Points: 60

Author: Jisoon Park(js00n.park)

Description:

Read this JPEG is broken. It will be fixed if you change somewhere by 1 bit.

source : SECCON CTF 2017 Quals.

Write-up

멀쩡한 jpeg 파일에서 1 bit를 수정했다고 한다. 수정으로 인한 curruption이 발생했을지 확인하기 위해 적당한 jpeg 파일 검사기를 찾아본다.

jpeg 파일을 검수해주는 프로그램은 여러가지가 있는데, 그 중에 가장 먼저 눈에 띈 jpeginfo를 받아서 빌드하였다.

jpeginfo를 이용해서 주어진 jpeg 파일을 테스트 해보면 에러메세지가 출력되는 것을 볼 수 있다.

파일의 처음부터 1 bit씩 바꾼 임시 파일을 만들어서 에러메세지가 발생하지 않는 파일을 찾는 프로그램을 작성하였다.

import subprocess
import os

data = open("tktk", "rb").read()

for i in xrange(0, len(data) * 8):
    block = i / 8
    index = i % 8
    new = chr(ord(data[block]) ^ (1 << index))

    fn = "tktk" + str(i)
    f = open(fn, "wb")
    f.write(data[0:block])
    f.write(new)
    f.write(data[block + 1:])
    f.close()

    cmd = "./jpeginfo -c " + fn + "; exit 0"
    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
    if (output[-8:-1] == "[ERROR]"):
        os.system("rm " + fn)
    else:
        print str(i) + " is ok!"

    if (i % 1000 == 0):
        print str(i)

실행시켜 보면, 검사에 걸리지 않는 파일이 10여개 정도 찾아지는데, 그 중에 아무거나 열어보면 플래그 이미지를 확인할 수 있었다.

Flag : SECCON{jp3g_study}

'writeups > Coding|misc.' 카테고리의 다른 글

plz variable  (0) 2019.11.25
input  (0) 2019.11.25
algo-auth  (0) 2019.11.25
PWN  (0) 2019.11.23
Run me!  (0) 2019.11.23

Description

Category: Forensic

Source: wargame.kr

Points: 295

Author: Jisoon Park(js00n.park)

Description:

Recovery the PNG image file!

but.. is this really "PNG" file? (NO STEGANOGRAPHY. THIS IS FORENSIC CHALLENGE)

Write-up

문제 화면에 들어가보면 이미지 패턴이 쭉 보이고 코드를 입력하는 부분이 있다. 별달리 주어지는게 없으니 일단 배경의 이미지를 다운로드 해보면 pattern.png임을 알 수 있다.

문제 설명에 스테가노그래피가 아니라 forensic이라고 나오는걸로 봐서 깨진 이미지인가 싶어 이런저런 이미지 파서로 정보를 살펴보았으나, 별다른 이상을 찾을 수 없었다.

한참을 살펴보다가 다른 png 파일과 비교해 보니, 헤더는 별다를 것이 없는데, footer 부분에 의미 있어보이는 문자열이 있었다. (왼쪽이 문제의 이미지, 오른쪽이 일반 이미지)

tEXt Software Japng r119로 검색을 해보니, Japng는 Java Animated PNG라는 의미라고 한다. 적당한 japng 분석 도구(https://www.reto-hoehener.ch/japng)를 받아서 이미지를 분석해보니, 이미지가 2장이 있었다.

export해서 비교해보니, 주어진 이미지와는 다르게 보이는 이미지가 한장 더 있었다. 처음에 문제 이미지를 봤을 때부터 QR 코드 이미지가 corrupt 된것 같다고 생각했어서 두 이미지를 겹쳐 보았다.

import Image

background = Image.open("0_pattern.png")
overlay = Image.open("1_pattern.png")

background = background.convert("RGBA")
overlay = overlay.convert("RGBA")

new_img = Image.blend(background, overlay, 0.5)
new_img.save("result.png","PNG")

[result.png]

합성된 이미지는 역시나 QR 코드 이미지였고, 온라인 QR decoder를 이용해서 encode된 값을 알아낼 수 있었다.

이 값을 문제 페이지에 넣으면 flag를 알아낼 수 있었다.

Flag : 4d501245fcd42318cae860e3ce2b1c57384b9627

'writeups > Forensic' 카테고리의 다른 글

wanna_smile  (0) 2019.11.25

Description

Category: Reversing

Source: pwnable.kr

Points: 50

Author: Jisoon Park(js00n.park)

Description:

Papa brought me a packed present! let's open it.

This is reversing task. all you need is binary

Write-up

먼저 flag 파일을 다운받고 file 명령을 이용해 파일의 기본 정보를 확인한다.

ELF executable 파일이므로, 리눅스에서 executable permission을 부여하고 실행시켜 본다.

파일의 내용을 개략적으로 살펴보기 위해 리눅스 strings 명령을 이용해 인식 가능한 문자열들을 확인한다.

string 실행 결과를 찾아봐도 위에서 flag 파일 실행 시 나왔던 메세지(I will malloc() and strcpy ....)가 보이지 않는다.
대신, 'UPX'라는 단어가 군데군데 등장하는 것을 알 수 있는데, UPX를 이용해서 packing 된 것으로 의심해보고, UPX packing을 해제해본다.

정상적으로 unpacking이 되는 것으로 미루어, UPX packing 되어 있었음을 확인할 수 있다.

다시 strings를 이용해 파일의 내용을 간략히 살펴보면, flag로 의심될만한 문장이 있음을 알 수 있고, 이를 submit 해보면 point를 획득할 수 있다.


  • IDA 등을 이용해 disassemble 해보면 문제에서 알려준 것처럼 해당 문자열이 메모리로 복사되는 것을 확인할 수 있다.

Flag : UPX...? sounds like a delivery service :)

'writeups > Reversing' 카테고리의 다른 글

Cr4ckZ33C0d3  (0) 2019.11.23
Cheesy  (0) 2019.11.23
keypad CrackMe  (0) 2019.11.23
DLL with notepad  (0) 2019.11.23
baby-re  (0) 2019.11.23

Description

Category: Pwnable

Source: pwnable.kr

Points: 10

Author: Jisoon Park(js00n.park)

Description:

Mommy! what is a file descriptor in Linux?

Write-up

주어진 fd.c 파일을 살펴보면, 15번째 라인에 친절하게 flag 파일의 내용을 보여주는 부분이 있다.

wiki

main() 함수의 첫 라인을 보면 하나 이상의 숫자를 입력받도록 되어 있고, 첫번째로 입력받은 숫자에서 0x1234를 뺀 값을 file descriptor로 하여 read() 함수를 호출하고 있다.

프로그램을 살펴보면 어디에도 fopen() 등을 통해 file descriptor를 얻어오는 부분이 없으므로 기본으로 주어지는 standard file descriptor를 사용해야 함을 유추할 수 있다.

file descriptor가 read() 함수에 사용되므로 사용자의 입력을 받는 stdin을 사용하면 되며, stdin은 0번 descriptor를 가지므로 0x1234에 해당하는 4660을 호출 인자로 주면 된다.

read() 함수를 통해 읽어들인 문자열이 "LETMEWIN"과 같은지 비교하기 때문에, 아래와 같은 방법으로 flag 값을 확인할 수 있다.

wiki

(굳이 python을 사용할 필요 없는 예제이나 참고를 위해 사용하였다.)

Flag : mommy! I think I know what a file descriptor is!!

'writeups > Pwnable' 카테고리의 다른 글

Pwn4  (0) 2019.11.23
Pwn3  (0) 2019.11.23
Pwn2  (0) 2019.11.23
Pwn1  (0) 2019.11.23
collision  (0) 2019.11.23

Description

Category: Reversing

Source: wargame.kr

Points: 428

Author: Jisoon Park(js00n.park)

Description:

DLL Reverse Engineering Challenge.

Can you reversing DLL File?

Write-up

주어진 압축파일을 풀어보면, notepad.exe와 blueh4g.dll 파일이 들어있다. 문제 제목이 DLL 리버싱인 만큼, notepad.exe는 쳐다도 안보고 일단 ida로 dll 파일을 열었다.

함수 목록을 쭉 살펴봤을 때, 별달리 두드려볼만한 함수가 보이지 않아 일단 가장 먼저 실행될 DllMain() 함수부터 살펴보았다.

fdwReason이 1이면, 즉 라이브러리가 처음 로딩되는 상황이면 start() 함수를 부른다.

실행파일 이름이 "notepad.exe"라면 StartAddress() 함수를 실행하는 스레드를 생성한다.

드디어 뭔가 출제자가 작성한듯한 코드가 나왔다. 일단 제목이 "blue4g.txt - 메모장"인 프로세스를 찾아서 그게 이 프로세스이면 "edit" 영역에 있는 문자열을 갖고 와서 10003388번지의 값과 비교하도록 하는것 같다. 비교 결과가 동일하다면 String이라는 전역변수에 있는 값을 보여주는 코드로 보인다. (흐리게 표시되는 지역변수 String과 진하게 표시되는 전역변수 String을 구분 못해서 한참 헷갈렸다.) 그렇다면 최종적으로 SetWindowTextA() 함수에서 출력될 값을 찾아보자.

런타임에 0x10001300 번지의 String 값을 확인할 수 있으면 될 것 같다.

IDA 디버깅은 익숙하지 못하니(...) ollydbg를 이용해서 notepad를 열었다.

일단 dll이 로딩된 주소를 확인하기 위해 View - Executable Modules에서 blueh4g.dll 파일의 주소를 확인하여 그쪽으로 이동했다.

베이스 주소가 0x6AF10000이라고 하니, IDA에서 확인했던 0x10001300 번지를 보려면 베이스 주소에 0x1300을 더하면 된다. (IDA에서 dll 로딩할 때 베이스 주소를 0x10000000으로 했어서..)

이 값을 이제 어디에 써야 하나 한참 고민했는데, 그냥 문제 페이지에 넣으면 flag를 알아낼 수 있었다.

Flag : e71c9d43ba4e78683864c23e16d8fdf4b27e00c1

'writeups > Reversing' 카테고리의 다른 글

Cr4ckZ33C0d3  (0) 2019.11.23
Cheesy  (0) 2019.11.23
keypad CrackMe  (0) 2019.11.23
flag  (0) 2019.11.23
baby-re  (0) 2019.11.23

Description

Category: Pwnable

Source: pwnable.kr

Points: 30

Author: Jisoon Park(js00n.park)

Description:

Daddy told me about MD5 hash collision today.

I wanna do something like that too!

Write-up

MD5 hash가 어쩌구 하지만 MD5와는 상관 없는 문제이다. 코드를 보면, 간단한 custom hash 알고리즘이 있고, 의도된 hash값을 만들어내는 문제이다.

main() 함수를 보면 argv[1]로 받아온 20byte의 문자열에 대한 hash를 계산하는데, 이 hash는 입력받은 문자열을 4byte씩 잘라서 정수 형태로 합산한 값이다.

정수 5개를 더해서 어떻게든 0x21DD09EC를 만들어 보자.

strlen() 함수를 이용해서 길이를 검사하므로, 문자열 중간에 0x00은 넣을 수 없다. 대신, 0x01을 16개 넣으면 0x01010101이 4번 들어가서 0x04040404가 될테니, 0x21DD09EC에서 0x04040404를 뺀 0x1DD905E8을 마지막에 넣어주면 된다.

little endian을 고려하여 아래와 같이 넣어주면 간단히 flag 값을 확인할 수 있다.

Flag : daddy! I just managed to create a hash collision :)

'writeups > Pwnable' 카테고리의 다른 글

Pwn4  (0) 2019.11.23
Pwn3  (0) 2019.11.23
Pwn2  (0) 2019.11.23
Pwn1  (0) 2019.11.23
fd  (0) 2019.11.23

Description

Category: Reversing

Source: DEFCON CTF 2016 Quals.

Points: 100

Author: Jisoon Park(js00n.park)

Description:

Get to reversing.

Write-up

문제 파일을 다운받아 정보를 확인해보고 실행해보면, 총 13개의 숫자를 입력받도록 되어있다.

동작 형태로 비추어 보아, 적절한 입력값을 찾아야 하는 문제임을 알 수 있다.

실제로 코드를 disassemble하여 확인해보면 13개의 미지수로 이루어진 방정식을 만족시키는 값을 찾으면 되는 문제인데, reversing을 통해 13개의 방정식 각각을 확인하고 이를 풀어볼 수도 있지만, 입력을 받는 포인트와 도달하고자 하는 포인트가 명확하니 symbolic execution을 통해 문제를 해결해보도록 한다.

먼저, 분석을 시작할 주소와 도달하고자 하는 주소, 탐색이 실패한 곳의 주소를 main 함수에서 확인한다.

해당 주소들과 symbolic execution 도구인 angr를 이용해서 flag 값을 찾는다.

(source code from : https://ctftime.org/writeup/3403)

import angr

START_ADDR = 0x00000000004028d9
AVOID_ADDR = 0x0000000000402941
FIND_ADDR = 0x000000000040293f
BASE_ADDR = 0x7fffffffe5c0
STACK_ADDR = 0x7fffffffe560
INPUT_ADDR = 0x7fffffffe560
INPUT_LENGTH = 13

p = angr.Project('baby-re')
state = p.factory.blank_state(addr=START_ADDR)
state.regs.rbp = BASE_ADDR
state.regs.rsp = STACK_ADDR

for i in range(INPUT_LENGTH):    
      s = state.se.BVS('Var[{}]'.format(i), 32, explicit_name=True)      
     state.memory.store(INPUT_ADDR + i * 4, s)   

path = p.factory.path(state)
ex = p.surveyors.Explorer(start=path, find=(FIND_ADDR,), avoid=(AVOID_ADDR,0x00000000004025e0))
ex.run()

print "The Flag: " + ex.found[0].state.posix.dumps(1)

angr을 사용하지 않고, 방정식을 풀어서 푸는 것도 가능하다.

http://duksctf.github.io/DCquals2016-baby-re/

Flag : Math is hard!

'writeups > Reversing' 카테고리의 다른 글

Cr4ckZ33C0d3  (0) 2019.11.23
Cheesy  (0) 2019.11.23
keypad CrackMe  (0) 2019.11.23
flag  (0) 2019.11.23
DLL with notepad  (0) 2019.11.23

+ Recent posts