# not_malware Writeup
For more writeups and content follow us on Twitter -- @RagnarSecurity
This challenge was in the category Reverse Engineering  for 150 points. This was one of the better challenges worth writing about for CSAW 2020.  
To start lets see what happens when we run the binary:
```WittsEnd2@DESKTOP-1N65HDS:[~/csaw/rev/not_malware]$ ./not_malwareWhat's your credit card number (for safekeeping) ?>> aaaaaaaaaaaaaaaaaaaaaaa```
It asks for a credit card number, and then exits (or it seems). Lets open this up in Ghidra and see what is actually going on. 
```cundefined8 FUN_001012bc(void)
{  int iVar1;  size_t sVar2;  undefined8 uVar3;  double dVar4;  char local_b6 [10];  undefined4 local_ac;  char local_a8 [32];  char local_88 [4];  char local_84;  char local_83;  char local_82;  char local_81;  char local_80;  char local_7f;  char local_7e;  char local_7d;  char local_7c;  char local_7b;  char local_7a;  char local_79;  char local_78;  char local_77;  char local_76;  char local_75;  char local_68 [8];  char local_60;  char local_5f;  char local_5e;  char local_5d;  char local_5c;  char acStack91 [20];  char local_47;  char acStack70 [30];  char local_28 [8];  int local_20;  int local_1c;  int local_18;  int local_14;  uint local_10;  int local_c;   FUN_001012a6();  printf("What\'s your credit card number (for safekeeping) ?\n>> ");  fgets(local_68,0x3c,stdin);  sVar2 = strlen(local_68);  if (0x3c < sVar2) {    puts("Well this was unnecessary.");                    /* WARNING: Subroutine does not return */    exit(1);  }  local_18 = 0x10;  dVar4 = pow(16.00000000,0.50000000);  local_18 = (int)(dVar4 - 1.00000000);  local_c = 0;  while (local_c < 8) {    local_28[local_c] = local_68[local_c];    local_c = local_c + 1;  }  local_28[local_c] = '\0';  iVar1 = strncmp(local_28,"yeetbank" + (long)local_18 * 9,8);  if (iVar1 != 0) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_60 != ':') {    puts("Get out.");                    /* WARNING: Subroutine does not return */    exit(1);  }  local_10 = (int)local_5f - 0x30;  local_1c = (int)local_5e + -0x30;  local_20 = (int)local_5d + -0x30;  if (local_5c != ':') {    puts("Get out.");                    /* WARNING: Subroutine does not return */    exit(1);  }  local_14 = 0;  while (local_14 < 0x14) {    uVar3 = FUN_00101288((ulong)local_10);    snprintf(local_b6,10,"%ld",uVar3);    local_88[local_14] = local_b6[local_20];    local_10 = local_10 + local_1c;    local_14 = local_14 + 1;  }  local_c = 0;  while (local_c < 0x14) {    local_a8[local_c] = local_68[local_c + 0xd];    local_c = local_c + 1;  }  if (local_a8[0] != local_88[0]) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[16] != local_78) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[11] != local_7d) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[3] != local_88[3]) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[7] != local_81) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[15] != local_79) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[1] != local_88[1]) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[12] != local_7c) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[19] != local_75) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[13] != local_7b) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[14] != local_7a) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[5] != local_83) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[9] != local_7f) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[8] != local_80) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[18] != local_76) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[6] != local_82) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[17] != local_77) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[2] != local_88[2]) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[10] != local_7e) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_a8[4] != local_84) {                    /* WARNING: Subroutine does not return */    exit(1);  }  if (local_47 != ':') {    puts("Get out.");                    /* WARNING: Subroutine does not return */    exit(1);  }  local_c = 0;  local_ac = 0x646e65;  while( true ) {    if (2 < local_c) {      puts("Thanks!");      FUN_00101229();      return 0;    }    if (*(char *)((long)&local_ac + (long)local_c) != local_68[local_c + 0x22]) break;    local_c = local_c + 1;  }                    /* WARNING: Subroutine does not return */  exit(1);}```
It looks like it executes some function before asking for our credit card number, then it performs logic to determine a credit card number, and then it prints a flag if a valid credit card. Lets break thsi down further. 
Lets look at these lines of code: 
```C  while (local_c < 8) {    local_28[local_c] = local_68[local_c];    local_c = local_c + 1;  }  local_28[local_c] = '\0';  iVar1 = strncmp(local_28,"yeetbank" + (long)local_18 * 9,8);  if (iVar1 != 0) {                    /* WARNING: Subroutine does not return */    exit(1);  }``````asm                             LAB_00101379                                    XREF[1]:     00101394(j)          00101379 8b 45 fc        MOV        EAX,dword ptr [RBP + local_c]        0010137c 48 98           CDQE        0010137e 0f b6 54        MOVZX      EDX,byte ptr [RBP + RAX*0x1 + -0x60]                 05 a0        00101383 8b 45 fc        MOV        EAX,dword ptr [RBP + local_c]        00101386 48 98           CDQE        00101388 88 54 05 e0     MOV        byte ptr [RBP + RAX*0x1 + -0x20],DL        0010138c 83 45 fc 01     ADD        dword ptr [RBP + local_c],0x1                             LAB_00101390                                    XREF[1]:     00101377(j)          00101390 83 7d fc 07     CMP        dword ptr [RBP + local_c],0x7        00101394 7e e3           JLE        LAB_00101379        00101396 8b 45 fc        MOV        EAX,dword ptr [RBP + local_c]        00101399 48 98           CDQE        0010139b c6 44 05        MOV        byte ptr [RBP + RAX*0x1 + -0x20],0x0                 e0 00        001013a0 8b 45 f0        MOV        EAX,dword ptr [RBP + local_18]        001013a3 48 63 d0        MOVSXD     RDX,EAX        001013a6 48 89 d0        MOV        RAX,RDX        001013a9 48 c1 e0 03     SHL        RAX,0x3        001013ad 48 01 c2        ADD        RDX,RAX        001013b0 48 8d 05        LEA        RAX,[s_yeetbank_00102020]                        = "yeetbank"                 69 0c 00 00        001013b7 48 8d 0c 02     LEA        RCX,[RDX + RAX*0x1]        001013bb 48 8d 45 e0     LEA        RAX=>local_28,[RBP + -0x20]        001013bf ba 08 00        MOV        EDX,0x8                 00 00        001013c4 48 89 ce        MOV        RSI,RCX        001013c7 48 89 c7        MOV        RDI,RAX        001013ca e8 71 fc        CALL       strncmp                                          int strncmp(char * __s1, char *                  ff ff        001013cf 85 c0           TEST       EAX,EAX        001013d1 74 0a           JZ         LAB_001013dd        001013d3 bf 01 00        MOV        EDI,0x1                 00 00        001013d8 e8 33 fd        CALL       exit                                             void exit(int __status)                 ff ff                             -- Flow Override: CALL_RETURN (CALL_TERMINATOR)```
The first thing that it checks is the first eight characters is equal to `iVar1 = strncmp(local_28,"yeetbank" + (long)local_18 * 9,8);` What the heck does this mean? My first instinct was to use GDB to figure this out. I set a breakpoint at the address where main begins; however, I get this output from GDB. 
```[Inferior 1 (process 387) exited with code 01]```
Huh? Why am I getting an error? How do I defeat this? If we remember from earlier there was this random function being called `FUN_001012a6();`. Lets see what it actually does. 
```Cvoid FUN_001012a6(void)
{  FUN_00101782();  FUN_0010186e();  FUN_001018b4();  return;}```
Huh, it calls three other functions. I quickly skimmed the functions and saw something that caught my eye:
```Cvoid FUN_001018b4(void)
{  long lVar1;   lVar1 = ptrace(PTRACE_TRACEME,0,1,0);  if (lVar1 == -1) {                    /* WARNING: Subroutine does not return */    exit(1);  }  return;}```
This is a common trick in RE. This is an anti-debugging technique using ptrace. Essentially, GDB uses ptrace (the tracer) in order to perform its breaking and stepping operations; however, this function detects whether another program is trying to trace the current program. If it is, it exits. I highly recommend reading `Programming Linux Anti-Reversing Techniques` by `Jacob Baines` to learn more. 
We can remove this function by patching it out. What I did was I patched `FUN_001012a6();`
For this, you need to open a copy of `not_malware in raw binary mode`, go to the address in the assembly where the function is being called, and patch out (by right clicking) all the bytes related to the function call to `NOP (0x90)`. 
After patching all of the bytes, you want to click on `file->export` and export it as a binary file. Now you have a patched binary and you can use GDB!
Now that we have GDB, we can set a breakpoint at main and figure out what it is doing! I first got the address of main by setting a break point at `printf`, and annoyingly step through instructions until I returned to the main function (my address in GDB was not exactly the same as in Ghidra). Once I did this, I set a break point at the string comparison to determine the actual values being compared. I saw that it was comparing my input to the value `softbank`. Thus; I know the first 8 characters are should be `softbank`.
From here, it got slightly tricky. After `softbank`, the required values are `:???:????????????????????:???` where `? = ascii character`. Lets break this down: 
```C  local_10 = (int)local_5f - 0x30; //:??X:????????????????????:???  local_1c = (int)local_5e + -0x30; //:?X?:????????????????????:???  local_20 = (int)local_5d + -0x30; //:X??:????????????????????:???  if (local_5c != ':') {    puts("Get out.");                    /* WARNING: Subroutine does not return */    exit(1);  }  local_14 = 0;  while (local_14 < 0x14) {    uVar3 = FUN_00101288((ulong)local_10);    snprintf(local_b6,10,"%ld",uVar3);    local_88[local_14] = local_b6[local_20];    local_10 = local_10 + local_1c;    local_14 = local_14 + 1;  }  local_c = 0;  while (local_c < 0x14) {    local_a8[local_c] = local_68[local_c + 0xd];    local_c = local_c + 1;  }```
It looks like the third unknown character (`local_10`) sets the value for `FUN_00101288`. Lets see what this does: 
```Clong FUN_00101288(uint param_1)
{  int iVar1;   srand(param_1);  iVar1 = rand();  return (long)iVar1;}```
`local_10` sets the seed for rand() and returns the value of `rand()`. As a result, it determined the value of the next 14 unknown characters (which were numbers). 
After doing some debugging, we determined that we should use 008. This will set the srand such than it will return 1. without changing the seed again (which is what the value of local_1c does).   
Therefore, our result so far was `softbank:008:11111111111111111111:???`. 
Last was to determine the last three character.```C  local_c = 0;  local_ac = 0x646e65;  while( true ) {    if (2 < local_c) {      puts("Thanks!");      FUN_00101229();      return 0;    }    if (*(char *)((long)&local_ac + (long)local_c) != local_68[local_c + 0x22]) break;    local_c = local_c + 1;  }```
Essentially, what this was doing was comparing the last three characters to the ascii value of 0x646e65 (note: it was reading local_ac in little endian). As a result, our final result was this: `softbank:008:11111111111111111111:end`, and we got the flag! flag{th4x_f0r_ur_cr3d1t_c4rd}