๋ถ์ผ : Reversing
๐ง ๋ฌธ์
๋ฌธ์ ๋ช : solve it
ํํธ : ๋ฌธ์ ์ค๋ฅ๊ฐ ์์ด์ ๋ฌธ์๋ฅผ ํ๋๋, ๋๋ณด๊ณ ์ง์ ์์ ํ๋ผ๊ณ ํ๋ค. ์ด๊ฒ ๊ฐ๋ฅํด?
๊ฐ์ง ๋ฌธ์ ๋ค์ ๋ชจ๋ ํ๋ฉด fake flag
๊ฐ ๋์จ๋ค. ์ง์ง ํ๋๊ทธ๋ฅผ ํ์ธํ๊ธฐ ์ํด์๋, ํด๋น exe
ํ์ผ์ด pyinstaller
๋ก ๋ง๋ค์ด์ง์ ์ธ์งํ๊ณ , ์ด๋ฅผ ๋์ปดํ์ผ ํ๋ฉด ์์ค์ฝ๋๋ฅผ ํ์ธํ ์ ์๊ณ ํ๋๊ทธ๋ฅผ ์ฐพ์ ์ ์๋ค.
๐จ ๊ฐ์ง ๋ฌธ์ ๋ชฉ๋ก
self.questions = [
{
'question': "Q1. ์น ํดํน ๊ธฐ๋ฒ์ด ์๋ ๊ฒ์?",
'choices': [
"SSTI",
"CSP",
"SSRF",
"CSRF",
"SQLi"
],
'correct_choice': "CSP",
},
{
'question': "Q2. 2022๋
๋ NIST์ ์ ์ ๋ ์์ ๋ด์ฑ ์ํธ๊ฐ ์๋ ๊ฒ์?",
'choices': [
"FALCON",
"SPHINCS+",
"CRYSTALS-KYBER",
"Lizard",
"CRYSTALS-DILITHIUM"
],
'correct_choice': "Lizard"
},
{
'question': "Q3. ๋ค์ ์ค ์คํ์ ์ต์๋จ์ ๊ฐ๋ฅดํค๋ ๋ ์ง์คํฐ๋?",
'choices': [
"ebp",
"edx",
"eax",
"eip",
"esp"
],
'correct_choice': "esp"
},
{
'question': "Q4. ๋ค์ ์ค ํ๋ฐ์ฑ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒ์?",
'choices': [
"๋ ์ง์คํธ๋ฆฌ",
"์๊ฒฉ ์ฌ์ฉ์ ์ ๋ณด",
"๋คํธ์ํฌ ์นด๋ ์ ๋ณด",
"ARP ํ
์ด๋ธ",
"์ธํฐ๋ท ์ฌ์ฉ ๊ธฐ๋ก"
],
'correct_choice': "๋ ์ง์คํธ๋ฆฌ"
},
{
'question': "Q5. 0x16 + 0b10110 = ?(10์ง์)",
'choices': [
"39",
"40",
"42",
"44",
"45"
],
'correct_choice': "44"
}
]
๐จ ์ง์ง ํ๋๊ทธ
def check_answer(self):
flag_arr = [[115, 99, 112, 67, 84, 70, 123, 102, 97, 107, 101, 95, 102, 108, 97, 103, 32, 58, 32, 80, 125],
[115, 99, 112, 67, 84, 70, 123, 104, 101, 49, 49, 111, 95, 112, 89, 116, 104, 48, 110, 95, 53, 48, 85, 114, 99, 51, 67, 111, 100, 51, 125]] ... ์ค๊ฐ ์๋ต ...
if self.current_question_index < len(self.questions):
self.set_question()
else:
result_str = ''
for _ in flag_arr[0]:
result_str += chr(_)
QMessageBox.information(self, "๊ฒ์ ์ข
๋ฃ", result_str)
self.close()
flag_arr[0]
์ ๊ฐ์ง ํ๋๊ทธ์ด๊ณ , flag_arr[1]
์ ์ง์ง ํ๋๊ทธ์ด๋ค. ๋ฐ๋ผ์, exe
ํ์ผ๋ก ๊ตฌ์ฑ๋ python
ํ๋ก๊ทธ๋จ์ ์์ค๋ฅผ ๋์ปดํ์ผํ๋ ๋ฌธ์ ์ด๋ค.
๐ง ๋ฌธ์ ํ์ด
- pyinstxtractor.py ์ค์น (https://sourceforge.net/project/pyinstallerextractor)
- HxD Editor (https://mh-nexus.de/en/hxd/)
- uncompyle6 (pip3 install uncompyle6)
python pyinstxtractor.py Hide_on_Problem.exe
pyinstxtractor.pyํ์ผ๋ก pyinstalle๋ก ๋ง๋ exe ํ์ผ์ ๋์ปดํ์ผ ํด์ค๋ค.
ํด๋๊ฐ ์์ฑ๋์๋ค.
ํด๋ ์์๋ ์ฌ๋ฌ ํ์ผ๋ค์ด ์๋ค. ์ฐ๋ฆฌ๊ฐ ๋ณผ ํ์ผ์ ๋๊ฐ์ด๋ค.
์์ค ํ์ผ์ ๋ฒ์ ์ ํ์ธํ์ฌ ํ์ผ ์๊ทธ๋์ฒ๋ฅผ ์์ ์ถ๊ฐํด์ค๋ค.
55 0D 0D 0A 01 00 00 00 00 00 00 00 00 00 00 00
์ด ๊ฐ์ base_library.zip
ํ์ผ ์์ ์๋ pyc
ํ์ผ๋ก ํ์ธํ๋ค.
์ด ์๊ทธ๋์ฒ ๊ฐ์ ์์ ํ์ผ ๋งจ ์์ ์ถ๊ฐํด์ pyc
ํ์ผ๋ก ์ ์ฅํด๋ณด์.
uncompyle6 result_src.pyc
uncompyle6 ๋ชจ๋๋ก ํด๋น ์์ค๋ฅผ ์ฝ๋๋ค.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap
class QuizForm(QMainWindow):
def __init__(self):
super().__init__()
# ๋ฌธ์ ์ ์ ํ์ง๋ค ๋ฆฌ์คํธ๋ก ๊ด๋ฆฌ
self.questions = [
{
'question': "Q1. ์น ํดํน ๊ธฐ๋ฒ์ด ์๋ ๊ฒ์?",
'choices': [
"SSTI",
"CSP",
"SSRF",
"CSRF",
"SQLi"
],
'correct_choice': "CSP",
},
{
'question': "Q2. 2022๋
๋ NIST์ ์ ์ ๋ ์์ ๋ด์ฑ ์ํธ๊ฐ ์๋ ๊ฒ์?",
'choices': [
"FALCON",
"SPHINCS+",
"CRYSTALS-KYBER",
"Lizard",
"CRYSTALS-DILITHIUM"
],
'correct_choice': "Lizard"
},
{
'question': "Q3. ๋ค์ ์ค ์คํ์ ์ต์๋จ์ ๊ฐ๋ฅดํค๋ ๋ ์ง์คํฐ๋?",
'choices': [
"ebp",
"edx",
"eax",
"eip",
"esp"
],
'correct_choice': "esp"
},
{
'question': "Q4. ๋ค์ ์ค ํ๋ฐ์ฑ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒ์?",
'choices': [
"๋ ์ง์คํธ๋ฆฌ",
"์๊ฒฉ ์ฌ์ฉ์ ์ ๋ณด",
"๋คํธ์ํฌ ์นด๋ ์ ๋ณด",
"ARP ํ
์ด๋ธ",
"์ธํฐ๋ท ์ฌ์ฉ ๊ธฐ๋ก"
],
'correct_choice': "๋ ์ง์คํธ๋ฆฌ"
},
{
'question': "Q5. 0x16 + 0b10110 = ?(10์ง์)",
'choices': [
"39",
"40",
"42",
"44",
"45"
],
'correct_choice': "44"
}
]
self.setWindowTitle("๋ฌธ์ ํ์ด ๊ฒ์")
self.setGeometry(500, 300, 400, 150)
self.main_widget = QWidget(self)
self.layout = QVBoxLayout(self.main_widget)
self.label_question = QLabel()
self.layout.addWidget(self.label_question)
self.radio_buttons = []
for _ in range(len(self.questions[0]['choices'])):
radio_button = QRadioButton()
self.layout.addWidget(radio_button)
self.radio_buttons.append(radio_button)
self.submit_button = QPushButton("์ ์ถ", self)
self.submit_button.clicked.connect(self.check_answer)
self.layout.addWidget(self.submit_button)
self.setCentralWidget(self.main_widget)
self.current_question_index = 0
self.set_question()
def set_question(self):
current_question = self.questions[self.current_question_index]
self.label_question.setText(current_question['question'])
for i, choice in enumerate(current_question['choices']):
self.radio_buttons[i].setText(choice)
def check_answer(self):
flag_arr = [[115, 99, 112, 67, 84, 70, 123, 102, 97, 107, 101, 95, 102, 108, 97, 103, 32, 58, 32, 80, 125],
[115, 99, 112, 67, 84, 70, 123, 104, 101, 49, 49, 111, 95, 112, 89, 116, 104, 48, 110, 95, 53, 48, 85, 114, 99, 51, 67, 111, 100, 51, 125]]
selected_choice = None
for radio_button in self.radio_buttons:
if radio_button.isChecked():
selected_choice = radio_button.text()
break
if selected_choice is None:
QMessageBox.warning(self, "๊ฒฝ๊ณ ", "๋ต์ ์ ํํด์ฃผ์ธ์.")
else:
current_question = self.questions[self.current_question_index]
if selected_choice == current_question['correct_choice']:
QMessageBox.information(self, "์ ๋ต", "์ ๋ต์
๋๋ค!")
else:
QMessageBox.information(self, "์ค๋ต", "์ค๋ต์
๋๋ค.")
self.close()
self.current_question_index += 1
if self.current_question_index < len(self.questions):
self.set_question()
else:
result_str = ''
for _ in flag_arr[0]:
result_str += chr(_)
QMessageBox.information(self, "๊ฒ์ ์ข
๋ฃ", result_str)
self.close()
app = QApplication(sys.argv)
window = QuizForm()
window.show()
sys.exit(app.exec_())
๋ฌธ์ ์ถ์ ์๋์ ๊ฐ์ด flag_arr
๋ฐฐ์ด์ ํ์ธํ ์ ์๋ค.
flag_arr = [[115, 99, 112, 67, 84, 70, 123, 102, 97, 107, 101, 95, 102, 108, 97, 103, 32, 58, 32, 80, 125],
[115, 99, 112, 67, 84, 70, 123, 104, 101, 49, 49, 111, 95, 112, 89, 116, 104, 48, 110, 95, 53, 48, 85, 114, 99, 51, 67, 111, 100, 51, 125]]
๐ง ๋ฌธ์ ํด๊ฒฐ
flag_arr = [[115, 99, 112, 67, 84, 70, 123, 102, 97, 107, 101, 95, 102, 108, 97, 103, 32, 58, 32, 80, 125],
[115, 99, 112, 67, 84, 70, 123, 104, 101, 49, 49, 111, 95, 112, 89, 116, 104, 48, 110, 95, 53, 48, 85, 114, 99, 51, 67, 111, 100, 51, 125]]
FLAG = ''
for ascii in flag_arr[1]:
FLAG += chr(ascii)
print(FLAG)
๊ฐ๋จํ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ํ๋๊ทธ๋ฅผ ์ป์ ์ ์๋ค.