2024년 들어 처음 뛴 CTF이다. 혼자서 응애맛 리버싱 1개를 슥삭했고, 다른 2개의 문제를 같이 고민하여 총 3문제 풀이에 기여를 했다. 대회 끝나고 1주일동안 아무것도 안하다가 주말에 서울갈 일정이랑 Real World CTF 뛸 생각에 미리 슥 백업해놓는다.
unstringify
최신의 opcode와 ymm 레지스터를 사용한다.
SIMD의 기술력은 세계제일
밖에 있어서 집컴에 ssh걸고 r2로 그래프를 봤을 때, 뭐가 없어서 바로 풀 수 있었다.
Analysis & AES
분석해보면 0x20byte 입력 이후 generate_key
의 결과로 setting된 ymm0
register의 값을 key로, 입력한 0x20byte의 input이 Permutate된(vpermq
) AES 한 단계를 수행하며, 그 결과가 vpcmpeqq
에서 참조하는 0x22c0
으로부터 0x20byte의 값과 동일해야 한다.
Key
vmovdqa
(main+132
)에 Breakpoint 걸고 ymm0
을 확인해 Key를 긁어올 수 있다.
v32_int8
을 확인해서 (Endian을 잘 지켜서) key 0003195a5b005902000315015c09015e42530d164d06420d2752423a630b540f
를 얻어냈다.
Encrypted
vpcmpeqq
에서 참조하는 encrypted flag는 51cc0fbea0262a146d758930ecfd461c0fa3b4798b62C90668ea03be2ac7f2c4
이다.
Restore
vaesenc
의 동작은 AES의 SubBytes, ShiftRow, MixColumn 을 순서대로 실행한 뒤 기존의 Key와 Blockwise하게 XOR한다. 역산하여 알아낸 키와 XOR, InvMixColumn, InvShiftRow, InvSubBytes 를 하면 (vpermq
를 거친 이후의) Flag가 나온다.
사실 해당 vpermq
는 ymm 레지스터를 permutate할 때 8byte 단위로 permutate하기에, 덩어리 4개를 잘 조합하면 Flag를 볼 수 있다. (눈썰미로 가능)
from aes import AES_implemented
enc = bytes.fromhex("51CC0FBEA0262A146D758930ECFD461C0FA3B4798B62C90668EA03BE2AC7F2C4")
# ymm0 = bytes.fromhex("3030303030303030303030303030303030303030303030303030303030303030") # Temp input
ymm1 = bytes.fromhex("0003195a5b005902000315015c09015e42530d164d06420d2752423a630b540f")
enc = bytes([en ^ y1 for en, y1 in zip(enc, ymm1)])
dec = AES_implemented(ymm1[:16]).decrypt_step(enc)
flg = dec[24:32] + dec[16:24] + dec[8:16] + dec[0:8]
print(flg)
# INS{T45k_Sp0n$0r3d_By_G4l4h4d<3}
FLAG: INS{T45k_Sp0n$0r3d_By_G4l4h4d<3}
풀면서 큰 어려움은 없었지만 솔직히 xmm ymm도 예쁘게 gdb에서 뽑아주는 플러그인이 있었으면 좋겠다.
만들어볼까
frown
작성중.
frown-revenge
작성중.
'Writeups' 카테고리의 다른 글
[bi0sctf 2024] writeups (0) | 2024.03.04 |
---|---|
[dicectf 2024] writeups (0) | 2024.02.06 |
[securinetsCTF 2023] tomojiksi (0) | 2024.01.16 |
[dreamhack.io] multipoint2 (0) | 2024.01.11 |