DefCamp CTF 2023 Quals-[Network] red-handed

yoobi·2023년 10월 23일
0

프로그램 분석

문제에서 chall.pcap 파일 한 개가 주어졌습니다. 해당 pcap 파일 내에는 BLE (블루투스) 통신 패킷이 존재하였으며, binwalk으로 확인하면 여러 PNG image 데이터가 같이 존재하는 것을 확인할 수 있습니다.

해당 PNG 파일을 추출하는 방향으로 문제 풀이 방법을 설정하였습니다.

취약점 분석

취약점은 아니고, 블루투스 통신 패킷을 처음보는거라 시간이 조금 걸렸지만, L2CAP 프로토콜 통신을 통해 PNG 파일이 통신되는 것을 확인할 수 있었습니다. SDU 패킷은 Start SDU, Continuation SDU, End SDU로 나뉘어져 통신이 진행되고 있었습니다.

공격 시나리오

해당 패킷을 모두 추출하여 이어붙이는 형태로 PNG 파일을 복원하는 것을 목표로 진행을 하였습니다. 해당 과정에서 Header, Control, FCS 등 통신 패킷에는 존재하지만 PNG 파일에는 들어가지 않는 데이터들을 삭제하는 과정을 거쳤습니다. 다만, Start-Continuation-End 과정이 1번이 아닌 여러번 반복되었고, End 이후 새로운 Start 이후에 몇 bytes를 삭제해야되는지를 알 수가 없었습니다. 처음 접근 방식으로 2번 째 과정 패킷을 1bytes 씩 삭제하며 붙이는 스크립트를 작성했었는데, 이론적으로는 가능해야하는데 FLAG를 획득하지 못했습니다(스크립트를 잘못 작성했을 수도 있습니다) 이후에 PNG-Fixer(https://github.com/Pourliver/PNG-Fixer)라는 툴을 사용하여 PNG 값 내 잘못된 데이터를 식별하고 hxd로 해당 데이터의 위치를 검색해서 bytes를 삭제하여 IDAT가 정확한 위치에 가도록 조정하였습니다.

위 과정을 통해 Start SDU 과정에서 6bytes를 추가적으로 삭제하면 PNG 파일을 획득할 수 있는 것을 확인하였습니다.

공격 코드

코드 내 bin 파일은 wireshark에서 SDU 통신 패킷을 하나씩 모두 저장한 것입니다. (단축키 Ctrl+Shift+x)

def concat(file_name):
    f1 = open("./out.png", 'rb')
    f2 = open(file_name, 'rb')
    tmp = f1.read() + f2.read()
    f3 = open("./out"+file_name+".png", 'wb')
    f3.write(bytes(tmp))
    f4 = open("./out.png", 'wb')
    f4.write(bytes(tmp))
    f4.close()
    f3.close()
    f1.close()
    f2.close()

def delete_bytes(num, file_name):
    f1 = open(file_name, 'rb')
    data = f1.read()
    f1.close()
    data = data[num:]
    #print(data)
    
    f2 = open(file_name, "wb")
    f2.write(bytes(data))
    f2.close()

def delete_last_bytes(file_name):
    f1 = open('../p2-original/'+file_name, 'rb')
    data = f1.read()
    f1.close()
    data = data[:-2]
    f2 = open(file_name, "wb")
    f2.write(bytes(data))
    f2.close()

ary = ['00-s.bin', '01-c.bin', '02-c.bin', '03-c.bin', '04-c.bin', '05-c.bin', '06-c.bin', '07-c.bin', '08-e.bin', '09-s.bin', '10-c.bin', '11-c.bin', '12-c.bin', '13-c.bin', '14-c.bin', '15-c.bin', '16-c.bin', '17-e.bin', '18-s.bin', '19-c.bin', '20-c.bin', '21-c.bin', '22-c.bin', '23-c.bin', '24-c.bin', '25-c.bin', '26-e.bin', '27-s.bin', '28-e.bin']
#ary = ['00-02.bin', '01-04.bin', '02-06.bin', '03-08.bin', '04-0a.bin', '05-0c.bin', '06-0e.bin', '07-10.bin', '10-16.bin', '11-18.bin', '12-1a.bin', '13-1c.bin', '14-1e.bin', '15-20.bin', '16-22.bin', '17-24.bin', '18-26.bin', '19-28.bin', '20-2a.bin', '21-2c.bin', '22-2e.bin', '23-30.bin', '24-32.bin', '25-34.bin', '26-36.bin', '27-38.bin', '28-3a.bin', '29-3c.bin']

for item in ary:
    delete_last_bytes(item)

for item in ary:
    if 's' in item:
        delete_bytes(13, item)
    else:
        delete_bytes(11, item)

f = open("./out.png", "w")
f.close()

for item in ary:
    if 's' in item:
        delete_bytes(6, item)
    concat(item)

f = open("./out.png", "rb")
data = f.read()
data = data[33:]
f.close()
f = open("./flag.png", "wb")
f.write(bytes(data))
f.close()

profile
this is yoobi

0개의 댓글