picoCTF 2018

Nguyễn Tín
3 min readDec 22, 2019

i know it’s kinda old but i really love this kind of rop challenge.

1. Source code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
#define BUFSIZE 16bool win1 = false;
bool win2 = false;
void win_function1() {
win1 = true;
void win_function2(unsigned int arg_check1) {
if (win1 && arg_check1 == 0xBAAAAAAD) {
win2 = true;
else if (win1) {
printf("Wrong Argument. Try Again.\n");
else {
printf("Nope. Try a little bit harder.\n");
void flag(unsigned int arg_check2) {
char flag[48];
FILE *file;
file = fopen("flag.txt", "r");
if (file == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
fgets(flag, sizeof(flag), file);

if (win1 && win2 && arg_check2 == 0xDEADBAAD) {
printf("%s", flag);
else if (win1 && win2) {
printf("Incorrect Argument. Remember, you can call other functions in between each win function!\n");
else if (win1 || win2) {
printf("Nice Try! You're Getting There!\n");
else {
printf("You won't get the flag that easy..\n");
void vuln() {
char buf[16];
printf("Enter your input> ");
return gets(buf);
int main(int argc, char **argv){setvbuf(stdout, NULL, _IONBF, 0);

// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);

2. Way of thinking

first of all, i audit the source a little bit and i notice that there are 4func that we need to focus on: vuln,win_function1 , win_function2 , flag .

to get to the flag, you have to line up the GOT win1 , win2 and pass an arg 0xdeadbaad before calling the flag function.

ok then, let’s jump to the m4g1k!!!

3. Hacking

first, let’s check if there are any protection on the binary (because the remote server don’t have gdb-peda, which have checksec, and of course from myself don’t have enough knowledge about testing the binary)

you can see, only NX on (and the ASLR off too), it’s make our exploit a lot easier

Now let dump disassembler mnemonics of those function we notice before

Now, let’s build our payload (i’m a one-liner command ^.^)

We got our offset from vuln which is 0x18 + 4 . The next 4 bytes is win_function1 to set the GOT win1 to true.

next the the win_function2 , we have to push 0xBAAAAAAD to set win2 to true (remember the flag address after the win_function2 )

and when you came to the flag function, push 0xDEADBAAD to stack

now, our final payload become

28 byte offset + '\xcb\x85\x04\x08' + '\xd8\x85\x04\x08' + '\x2b\x86\x04\x08' + '\xad\xaa\xaa\xba' + '\xad\xba\xad\xde'

enjoy hacking!!!