๋ฌธ์ : DreamHack โ Easy Assembly ๋ถ๋ฅ: Reversing ๋์ด๋: ๐ฅ Bronze 4 FLAG:
DH{UGxlYXNlIGRvIG5vdCBiYXNlNjQgZGVjb2RlIGl0Lg==}
libc ์์ด ์์ผ๋ก ์ง ์์ ์ด์
๋ธ๋ฆฌ ํฌ๋๋ฏธ๋ค. <key>๋ฅผ ์ธ์๋ก ๋ฐ์ ๋ง์ผ๋ฉด "You nailed it!"์ ์ถ๋ ฅํ๋ค. ๊ฒ์ฌ ๋ก์ง์ด XOR ๋ช ์ค๋ฟ์ด๋ผ, ๊ทธ ์์ ๋ค์ง์ผ๋ฉด ์ ๋ต ํค๊ฐ ๊ทธ๋๋ก ๊ณ์ฐ๋๋ค.

๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | Easy Assembly |
| ๋์ด๋ | ๐ฅ Bronze 4 |
| ๋ถ๋ฅ | Reversing (x86 32-bit ELF, static, not stripped) |
| ์ ๊ณต ํ์ผ | prob (์ง์ ์์ฑํ ์ด์
๋ธ๋ฆฌ ๋ฐ์ด๋๋ฆฌ) |
| ํต์ฌ ๊ธฐ๋ฒ | XOR ๋น๊ต์ ์ญ์ฐ โ ์ ๋ต ํค = enc_flag ^ len |
์ฌ๋ณผ์ด ๋จ์ ์์ด(check_password, enc_flag) ํ๋ฆ ํ์
์ด ์ฝ๋ค. ๊ฒ์ฌ์ ํ ์ค๋ง ๋ค์ง์ผ๋ฉด ๋๋๋ค.
๐ฌ ์ ์ฐฐ โ ์ ๋ ฅ์ enc_flag์ ๋์กฐํ๋ค
entry0๋ ์ธ์ <key>๋ฅผ ๋ฐ์ check_password(enc_flag, key)๋ฅผ ๋ถ๋ฅด๊ณ , ๋ฐํ๊ฐ์ด 0์ด๋ฉด ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
mov edi, enc_flag ; 0x804a000 (์ํธํ๋ ์ ๋ต)
mov esi, ecx ; argv[1] = ์ฌ์ฉ์ ์
๋ ฅ key
call check_password
cmp eax, 0
je success ; 0 ์ด๋ฉด "You nailed it!"enc_flag๋ .data์ ๋ฐํ 42~48๋ฐ์ดํธ์ง๋ฆฌ ๋ฐ์ดํธ์ด์ด๋ค. ์ฌ์ฉ์ ์
๋ ฅ์ ์ด ๊ฐ๊ณผ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋์กฐํ๋์ง๊ฐ ์ ๋ถ์ด๋ฏ๋ก, check_password๋ฅผ ๋ฏ๋๋ค.
๐ฃ ํต์ฌ โ XOR ๋น๊ต์์ ๋ค์ง๋๋ค
check_password๋ ํ ๊ธ์์ฉ ๋๋ ์งง์ ๋ฃจํ๋ค.
r2 -q -c "pd 16 @ 0x0804906b" prob![ํด๋ฆญํ์ฌ ํ๋ radare2 check_password ๋์ค์ด์
๋ธ โ input[i] ^ len ^ enc_flag[i] ๋ฅผ ๋์ (or)ํด 0์ธ์ง ๊ฒ์ฌ](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-easy-assembly-writeup%2F01_check_disasm.png&w=3840&q=75)
ํต์ฌ ์ธ ์ค์ด ์ด๋ ๋ค.
mov dl, byte [esi] ; dl = input[i]
xor dl, byte [len] ; dl ^= len (์
๋ ฅ ๊ธธ์ด)
xor dl, byte [edi] ; dl ^= enc_flag[i]
or ecx, dl ; ๊ฒฐ๊ณผ๋ฅผ ecx์ ๋์ ์ฆ ๋งค ์๋ฆฌ๋ง๋ค input[i] ^ len ^ enc_flag[i]๋ฅผ ๊ตฌํด ecx์ OR๋ก ์๊ณ , ๋๊น์ง ์ ๋ถ 0์ด์ด์ผ(=ecx==0) ํต๊ณผํ๋ค. ์ด ์กฐ๊ฑด์ ์๋ฆฌ๋ณ๋ก ํ๋ฉด ์ ๋ต ํค๊ฐ ๊ณง๋ฐ๋ก ๋์จ๋ค.
input[i] ^ len ^ enc_flag[i] = 0
โ input[i] = enc_flag[i] ^ len์ฌ๊ธฐ์ len์ ์
๋ ฅ ํค์ ๊ธธ์ด๋ค. ์ ๋ต ํค์ ๊ธธ์ด๊ฐ ๊ณง ํ๋๊ทธ ๊ธธ์ด(48)์ด๋ฏ๋ก len = 48 = 0x30. ๊ฒฐ๊ตญ ์ ๋ต ํค = enc_flag ^ 0x30 ์ด๋ค. XOR์ ์๊ธฐ์ญ์์ด๋ผ, ์ ์ฅ๋ enc_flag๋ฅผ ๊ฐ์ 0x30์ผ๋ก ๋ค์ XORํ๋ฉด ์๋ฌธ์ด ๋ณต์๋๋ค.
๐ฏ ํ์ด โ enc_flag ^ 0x30
enc_flag 48๋ฐ์ดํธ๋ฅผ ๋ฝ์ 0x30์ผ๋ก XORํ๋ค. ์ค๊ฐ์ ์๋ 0x00 ๋ฐ์ดํธ๋ ์ค์ ๋ฐ์ดํฐ(0x00 ^ 0x30 = '0')์ด๋ฏ๋ก ๋๋ก ๋์ง ์๋ ๊ฒ ํจ์ ์ด๋ค.
# decode.py
import base64
data = open("prob", "rb").read()
off = data.find(bytes.fromhex("74784b6577485c69")) # enc_flag ์์
enc = data[off:off+48] # 48๋ฐ์ดํธ (๋ด๋ถ 0x00 ๋ ๋ฐ์ดํฐ)
flag = bytes(b ^ 0x30 for b in enc).decode()
print("FLAG :", flag)
print("b64 ์์ชฝ :", base64.b64decode(flag[3:-1]).decode())
๋ณต์๋ ํ๋๊ทธ์ DH{} ์์ชฝ์ base64์ธ๋ฐ, ํ์ด ๋ณด๋ฉด Please do not base64 decode it.์ด๋ผ๋ ์ฅ๋์ด ๋ค์ด ์๋ค. ๋ณต์ํ ํค๋ฅผ ์ค์ ๋ฐ์ด๋๋ฆฌ์ ๋ฃ์ด ๊ฒ์ฆํ๋ค.
./prob "DH{UGxlYXNlIGRvIG5vdCBiYXNlNjQgZGVjb2RlIGl0Lg==}"
You nailed it!์ด ๋ด๋ค. ๋ณต์ํ ํค๊ฐ ์ ๋ต์ด ๋ง๋ค.
FLAG: DH{UGxlYXNlIGRvIG5vdCBiYXNlNjQgZGVjb2RlIGl0Lg==}
๐ ๊ฒฐ๋ก
๊ฒ์ฌ์์ ๊ณง ์ ๋ต์ ๋ฐฉ์ ์์ด๋ค.
ํฌ๋๋ฏธ์ ๋น๊ต ๋ฃจํด์ "์ ๋ ฅ์ด ๋ง๋๊ฐ"๋ฅผ ํ์ ํ๋ ค๊ณ ์ ๋ต๊ณผ์ ๊ด๊ณ๋ฅผ ์ฝ๋๋ก ์ ์ด ๋ ๊ฒ์ด๋ค. ๊ทธ ๊ด๊ณ๊ฐ XOR์ฒ๋ผ ๊ฐ์ญ์ด๋ฉด, ํ์ ์์ ์ ๋ ฅ์ ๋ํด ํ๊ธฐ๋ง ํ๋ฉด ์ ๋ต์ด ๊ทธ๋๋ก ๋จ์ด์ง๋ค. ๋ธ๋ฃจํธํฌ์ค๋ ํ์ ์๋ค.
๋์ด๋ผ๊ณ ๋ค ๋์ด ์๋๋ค.
enc_flag ์ค๊ฐ์ 0x00์ ๋ฌธ์์ด ๋์ผ๋ก ์ฐฉ๊ฐํ๋ฉด ํ๋๊ทธ๊ฐ ์๋ฆฐ๋ค. ์ด ๋ฐ์ด๋๋ฆฌ๋ ๊ธธ์ด๋ฅผ ๋ฐ๋ก ๋ค๊ณ ๋ค๋๋ฉฐ ๊ทธ ๋ฐ์ดํธ๋ ๋ฐ์ดํฐ๋ก ์ด๋ค. ์ธ์ฝ๋ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋ ๋ ์ข
๋จ์ ํจ๋ถ๋ก ๊ฐ์ ํ์ง ์๋ ์ต๊ด์ด ํ์ํ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ