Writeups

View on GitHub

Spying Through the Webdoor

Category: Reverse Engineering

We are given an exectubale. Based on a quick reverse engineering, we can see that the binary is a web server.

On running strings through the binary, we can see an interesting one.

┌──(greenpanda999㉿zacian)-[~/Desktop/Hax/webdoor]
└─$ strings arc-httpd | grep ARC
Congrats! The key is: ARC%s

We find the xref to this string in Ghidra. To get to the string, we can see the following function condition.

  if ((int)sVar2 == 0x17) {
    __s2 = (void *)do_hash(__s,0x17,&DAT_001050b0,8);
    __dest = malloc(0x17);
    memcpy(__dest,&DAT_00105ea1,0x17);
    iVar1 = memcmp(__dest,__s2,0x17);
    if (iVar1 == 0) {
      fwrite("HTTP/1.1 200 OK\r\n",1,0x11,param_1);
      fwrite("Server: arc-httpd\r\n",1,0x13,param_1);
      fwrite("Connection: close\r\n",1,0x13,param_1);
      fwrite(&DAT_00105ef3,1,2,param_1);
      fprintf(param_1,"Congrats! The key is: ARC%s\r\n",__s);
      fprintf(param_1,"\nexecuting command: %s\n",local_10c8);
      ....

We need to clear ```memcmp==0``, which is basically an hash match. It needs to be compared to &DAT_00105ea1

void * do_hash(long param_1,int param_2,long param_3,int param_4)

{
  void *pvVar1;
  int local_14;
  
  pvVar1 = malloc((long)param_2);
  if (pvVar1 == (void *)0x0) {
    perror("malloc");
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  for (local_14 = 0; local_14 < param_2; local_14 = local_14 + 1) {
    *(byte *)((long)pvVar1 + (long)local_14) =
         (*(byte *)(param_1 + local_14) ^ *(byte *)(param_3 + local_14 % param_4)) + 0x42;
  }
  return pvVar1;
}

I wrote a quick z3 script to solve this.

from z3 import *

final = [ 0x41, 0xfc, 0x1b, 0x18, 0xff, 0x10, 0x0d, 0xb4, 0x1d, 0xfc, 0x1b, 0x18, 0xff, 0x11, 0x0d, 0xb7, 0x18, 0xff, 0x16, 0x0d, 0xe5, 0x04, 0x3b, 0x00 ]
param_3 = [ 0x84, 0xe2, 0x96, 0x84, 0xe2, 0x96, 0x84, 0x20, ]
param_3_bitvec = [ BitVec('param_3_%d' % i, 8) for i in range(len(param_3)) ]


def main():
    s = Solver()
    param1 = [ BitVec('param1_%d' % i, 8) for i in range(0x17) ]
    for i in range(0x17):
        s.add(param1[i] >= 0x20)
        s.add(param1[i] <= 0x7e)
        s.add(final[i] == ((param1[i] ^ param_3_bitvec[i%8])+ 0x42)%0x100)
    for i in range(8):
        s.add(param_3_bitvec[i] == param_3[i])

    print(s.check())
    vals = s.model()
    for i in range(0x17):
        print(chr(vals[param1[i]].as_long()), end='')

if __name__ == '__main__':
    main()

We get the flag.

ARCXOR_XOR_XOR_YOUR_BOAT}