# A secure database
## Description
A friend of mine told me that he has an encrypted leaked database somewhere on his server. He has been willing to give me a program to retrieve it, but he did not give me the password used to decrypt the database. Can you find it?
He also told me that his program was super safe, and that I would not be able to use my tools on it.
Creator : Nofix
## What are we dealing with?
```kali@kali:~/Downloads/secure_db$ ls -ltotal 24-rw-r--r-- 1 kali kali 21068 May  9 12:06 secure_dbkali@kali:~/Downloads/secure_db$ file secure_db secure_db: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, not stripped
kali@kali:~/Downloads/secure_db$ chmod +x secure_db kali@kali:~/Downloads/secure_db$ ./secure_db Usage : ./secure_db output_filekali@kali:~/Downloads/secure_db$ ./secure_db fooHi Doge ! ░░░░░░░░░▄░░░░░░░░░░░░░░▄░░░░░░░░░░░░▌▒█░░░░░░░░░░░▄▀▒▌░░░░░░░░░░░▌▒▒█░░░░░░░░▄▀▒▒▒▐░░░░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐░░░░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐░░░░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌░░░░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌░░░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐░░░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌░░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌░▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐░▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐░░▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌░░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐░░░░▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌░░░░░░▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀░░░░░░░░░▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▀▀░░░░░░░░Please input the password :-> hellookWrong password sorry, exiting.```
It's a 32-bit executable that takes a single filename argument and a single password via STDIN.
## Analysis
Open the binary in Ghidra and find where the input is accepted.
```cundefined4 FUN_0804870a(void){  size_t sVar1;  undefined4 uVar2;  int *in_ECX;  int in_GS_OFFSET;  bool bVar3;  undefined4 local_30;  undefined4 local_2c;  undefined4 local_28;  undefined4 local_24;  int local_20;  undefined4 uStack24;  int *local_14;   uStack24 = 0x8048716;  local_20 = *(int *)(in_GS_OFFSET + 0x14);  local_14 = in_ECX;  if (*in_ECX != 2) {    __printf_chk();                    /* WARNING: Subroutine does not return */    exit(1);  }  _DAT_0804d0a4 = FUN_08048b70();  local_30 = 0;  local_2c = 0;  local_28 = 0;  local_24 = 0;  __printf_chk();  fgets(&DAT_0804d0c0,0x50,*(FILE **)PTR_stdin_0804cffc);  sVar1 = strcspn(&DAT_0804d0c0,"\n");  (&DAT_0804d0c0)[sVar1] = 0;  strncpy((char *)&local_30,&DAT_0804d0c0,0x10);  bVar3 = false;  FUN_08048a90();  if (bVar3) {    puts("ok");    if (((((DAT_0804d0c0 == *PTR_DAT_0804d068) && (DAT_0804d0c1 == PTR_DAT_0804d068[1])) &&         (DAT_0804d0c2 == PTR_DAT_0804d068[2])) &&        (((DAT_0804d0c3 == PTR_DAT_0804d068[3] && (DAT_0804d0c4 == PTR_DAT_0804d068[4])) &&         ((DAT_0804d0c5 == PTR_DAT_0804d068[5] &&          ((DAT_0804d0c6 == PTR_DAT_0804d068[6] && (DAT_0804d0c7 == PTR_DAT_0804d068[7])))))))) &&       ((DAT_0804d0c8 == PTR_DAT_0804d068[8] &&        (((((DAT_0804d0c9 == PTR_DAT_0804d068[9] && (DAT_0804d0ca == PTR_DAT_0804d068[10])) &&           (DAT_0804d0cb == PTR_DAT_0804d068[0xb])) &&          ((DAT_0804d0cc == PTR_DAT_0804d068[0xc] && (DAT_0804d0cd == PTR_DAT_0804d068[0xd])))) &&         (DAT_0804d0ce == PTR_DAT_0804d068[0xe])))))) {      puts("The password is valid.");      FUN_08048c60();      puts("Received and *hopefully* sucessfuly decrypted the database with the given password.");      uVar2 = 0;    }    else {      puts("Wrong password sorry, exiting.");      uVar2 = 1;    }    if (local_20 != *(int *)(in_GS_OFFSET + 0x14)) {      FUN_0804a460();      __libc_start_main();      do {                    /* WARNING: Do nothing block with infinite loop */      } while( true );    }    return uVar2;  }  func_0x8b927754();                    /* WARNING: Bad instruction - Truncating control flow here */  halt_baddata();}```
That's just an ugly looking string comparison. What's in `PTR_DAT_0804d068`?
```                             PTR_DAT_0804d068                                XREF[1]:     FUN_0804870a:080487ec(R)          0804d068 e4 ac 04 08     addr       DAT_0804ace4                                     = 4Eh        0804d06c f5 ac 04 08     addr       s_You_can't_debug_me_:*_0804acf5                 = "You can't debug me :*"
What's in DAT_0804ace4?
                             DAT_0804ace4                                    XREF[2]:     FUN_0804870a:080487f5(R),                                                                                           0804d068(*)          0804ace4 4e              undefined1 4Eh                             DAT_0804ace5                                    XREF[1]:     FUN_0804870a:08048804(R)          0804ace5 33              undefined1 33h                             DAT_0804ace6                                    XREF[1]:     FUN_0804870a:08048814(R)          0804ace6 6b              undefined1 6Bh                             DAT_0804ace7                                    XREF[1]:     FUN_0804870a:08048824(R)          0804ace7 76              undefined1 76h                             DAT_0804ace8                                    XREF[1]:     FUN_0804870a:08048834(R)          0804ace8 69              undefined1 69h                             DAT_0804ace9                                    XREF[1]:     FUN_0804870a:08048844(R)          0804ace9 58              undefined1 58h                             DAT_0804acea                                    XREF[1]:     FUN_0804870a:08048854(R)          0804acea 37              undefined1 37h                             DAT_0804aceb                                    XREF[1]:     FUN_0804870a:08048864(R)          0804aceb 2d              undefined1 2Dh                             DAT_0804acec                                    XREF[1]:     FUN_0804870a:08048874(R)          0804acec 76              undefined1 76h                             DAT_0804aced                                    XREF[1]:     FUN_0804870a:08048884(R)          0804aced 58              undefined1 58h                             DAT_0804acee                                    XREF[1]:     FUN_0804870a:08048890(R)          0804acee 45              undefined1 45h                             DAT_0804acef                                    XREF[1]:     FUN_0804870a:0804889c(R)          0804acef 71              undefined1 71h                             DAT_0804acf0                                    XREF[1]:     FUN_0804870a:080488a8(R)          0804acf0 76              undefined1 76h                             DAT_0804acf1                                    XREF[1]:     FUN_0804870a:080488b4(R)          0804acf1 6c              undefined1 6Ch                             DAT_0804acf2                                    XREF[1]:     FUN_0804870a:080488c0(R)          0804acf2 70              undefined1 70h        0804acf3 00              ??         00h        0804acf4 00              ??         00h```
In ASCII, that comes out to `N3kviX7-vXEqvlp`.
```kali@kali:~/Downloads/secure_db$ perl -e 'print "\x4e\x33\x6B\x76\x69\x58\x37\x2d\x76\x58\x45\x71\x76\x6c\x70\n"'N3kviX7-vXEqvlp```
Is that the password?
```kali@kali:~/Downloads/secure_db$ ./secure_db fooHi Doge ! ░░░░░░░░░▄░░░░░░░░░░░░░░▄░░░░░░░░░░░░▌▒█░░░░░░░░░░░▄▀▒▌░░░░░░░░░░░▌▒▒█░░░░░░░░▄▀▒▒▒▐░░░░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐░░░░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐░░░░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌░░░░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌░░░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐░░░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌░░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌░▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐░▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐░░▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌░░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐░░░░▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌░░░░░░▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀░░░░░░░░░▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▀▀░░░░░░░░Please input the password :-> N3kviX7-vXEqvlpokWrong password sorry, exiting.```
That didn't work, so there must be some transformation.Before the string comparison, we get the input from STDIN here:
```c  fgets(&DAT_0804d0c0,0x50,*(FILE **)PTR_stdin_0804cffc);  sVar1 = strcspn(&DAT_0804d0c0,"\n");  (&DAT_0804d0c0)[sVar1] = 0;  strncpy((char *)&local_30,&DAT_0804d0c0,0x10);  bVar3 = false;  FUN_08048a90();  if (bVar3) {```
It takes the string and replaces \n with a NULL terminator.The buffer is 16 bytes (15 chars + '\0')
What does `FUN_08048a90()` do?The decompiled C code is useless:
```cvoid FUN_08048a90(void){  return;}```
Here's the disassembly:
```                             **************************************************************                             *                          FUNCTION                          *                             **************************************************************                             undefined FUN_08048a90()             undefined         AL:1           <RETURN>             undefined4        Stack[-0x14]:4 local_14                                XREF[1]:     08048aa4(*)                               FUN_08048a90                                    XREF[1]:     FUN_0804870a:080487d4(c)          08048a90 55              PUSH       EBP        08048a91 57              PUSH       EDI        08048a92 e8 2e 05        CALL       __i686.get_pc_thunk.cx                           undefined __i686.get_pc_thunk.cx()                 00 00        08048a97 81 c1 69        ADD        ECX,0x4569                 45 00 00        08048a9d 56              PUSH       ESI        08048a9e 53              PUSH       EBX        08048a9f e8 00 00        CALL       LAB_08048aa4                 00 00                             LAB_08048aa4                                    XREF[1]:     08048a9f(j)          08048aa4 83 04 24 05     ADD        dword ptr [ESP]=>local_14,offset LAB_08048aa9        08048aa8 c3              RET                             LAB_08048aa9                                    XREF[1]:     FUN_08048a90:08048aa4(*)          08048aa9 8d b9 c0        LEA        EDI,[ECX + 0xc0]                 00 00 00        08048aaf 89 fe           MOV        ESI,EDI        08048ab1 eb 0d           JMP        LAB_08048ac0        08048ab3 90              ??         90h        08048ab4 90              ??         90h        08048ab5 90              ??         90h        08048ab6 90              ??         90h        08048ab7 90              ??         90h        08048ab8 90              ??         90h        08048ab9 90              ??         90h        08048aba 90              ??         90h        08048abb 90              ??         90h        08048abc 90              ??         90h        08048abd 90              ??         90h        08048abe 90              ??         90h        08048abf 90              ??         90h                             LAB_08048ac0                                    XREF[2]:     08048ab1(j), 08048ad4(j)          08048ac0 8b 16           MOV        EDX,dword ptr [ESI]        08048ac2 83 c6 04        ADD        ESI,0x4        08048ac5 8d 82 ff        LEA        EAX,[EDX + 0xfefefeff]                 fe fe fe        08048acb f7 d2           NOT        EDX        08048acd 21 d0           AND        EAX,EDX        08048acf 25 80 80        AND        EAX,0x80808080                 80 80        08048ad4 74 ea           JZ         LAB_08048ac0        08048ad6 89 c2           MOV        EDX,EAX        08048ad8 c1 ea 10        SHR        EDX,0x10        08048adb a9 80 80        TEST       EAX,0x8080                 00 00        08048ae0 0f 44 c2        CMOVZ      EAX,EDX        08048ae3 8d 56 02        LEA        EDX,[ESI + 0x2]        08048ae6 0f 44 f2        CMOVZ      ESI,EDX        08048ae9 89 c2           MOV        EDX,EAX        08048aeb 00 c2           ADD        DL,AL        08048aed 83 de 03        SBB        ESI,0x3        08048af0 29 fe           SUB        ESI,EDI        08048af2 74 3c           JZ         LAB_08048b30        08048af4 0f b6 a9        MOVZX      EBP,byte ptr [ECX + 0xa0]                 a0 00 00 00        08048afb 31 db           XOR        EBX,EBX        08048afd 8d 76 00        LEA        ESI,[ESI]                             LAB_08048b00                                    XREF[1]:     08048b25(j)          08048b00 89 d8           MOV        EAX,EBX        08048b02 31 d2           XOR        EDX,EDX        08048b04 89 d9           MOV        ECX,EBX        08048b06 f7 f6           DIV        ESI        08048b08 8b 44 24 14     MOV        EAX,dword ptr [ESP + 0x14]        08048b0c 83 e1 03        AND        ECX,0x3        08048b0f 83 c3 01        ADD        EBX,0x1        08048b12 c1 e1 03        SHL        ECX,0x3        08048b15 d3 f8           SAR        EAX,CL        08048b17 89 c1           MOV        ECX,EAX        08048b19 89 e8           MOV        EAX,EBP        08048b1b 32 04 17        XOR        AL,byte ptr [EDI + EDX*0x1]        08048b1e 31 c8           XOR        EAX,ECX        08048b20 39 de           CMP        ESI,EBX        08048b22 88 04 17        MOV        byte ptr [EDI + EDX*0x1],AL        08048b25 75 d9           JNZ        LAB_08048b00        08048b27 89 f6           MOV        ESI,ESI        08048b29 8d bc 27        LEA        EDI,[EDI]                 00 00 00 00                             LAB_08048b30                                    XREF[1]:     08048af2(j)          08048b30 5b              POP        EBX        08048b31 5e              POP        ESI        08048b32 5f              POP        EDI        08048b33 5d              POP        EBP        08048b34 c3              RET        08048b35 8d              ??         8Dh        08048b36 74              ??         74h    t        08048b37 26              ??         26h    &        08048b38 00              ??         00h        08048b39 8d              ??         8Dh        08048b3a bc              ??         BCh        08048b3b 27              ??         27h    '        08048b3c 00              ??         00h        08048b3d 00              ??         00h        08048b3e 00              ??         00h        08048b3f 00              ??         00h        08048b40 53              ??         53h    S        08048b41 e8              ??         E8h        08048b42 7a              ??         7Ah    z        08048b43 fe              ??         FEh        08048b44 ff              ??         FFh        08048b45 ff              ??         FFh        08048b46 81              ??         81h        08048b47 c3              ??         C3h        08048b48 ba              ??         BAh        08048b49 44              ??         44h    D        08048b4a 00              ??         00h        08048b4b 00              ??         00h        08048b4c 83              ??         83h        08048b4d ec              ??         ECh        08048b4e 14              ??         14h        08048b4f ff              ??         FFh        08048b50 74              ??         74h    t        08048b51 24              ??         24h    $        08048b52 1c              ??         1Ch        08048b53 e8              ??         E8h        08048b54 f8              ??         F8h        08048b55 fa              ??         FAh        08048b56 ff              ??         FFh        08048b57 ff              ??         FFh        08048b58 83              ??         83h        08048b59 f8              ??         F8h        08048b5a 0f              ??         0Fh        08048b5b 0f              ??         0Fh        08048b5c 94              ??         94h        08048b5d 83              ??         83h        08048b5e 64              ??         64h    d        08048b5f 00              ??         00h        08048b60 00              ??         00h        08048b61 00              ??         00h        08048b62 83              ??         83h        08048b63 c4              ??         C4h        08048b64 18              ??         18h        08048b65 5b              ??         5Bh    [        08048b66 c3              ??         C3h        08048b67 89              ??         89h        08048b68 f6              ??         F6h        08048b69 8d              ??         8Dh        08048b6a bc              ??         BCh        08048b6b 27              ??         27h    '        08048b6c 00              ??         00h        08048b6d 00              ??         00h        08048b6e 00              ??         00h        08048b6f 00              ??         00h```
That's... something I guess. It's probably faster to solve this 1 character at a time than to understand WTF this is doing.
Let's try `angr` to solve this.
## Solution
```python#!/usr/bin/env python3import angr, time, claripy
BINARY='./secure_db'OUTFILE='out.db't=time.time()proj = angr.Project(BINARY, auto_load_libs=False)print(proj.arch)print(proj.filename)print("Entry: 0x%x" % proj.entry)
FIND=0x080488d6 # puts("The password is valid.");AVOID=0x0804890a # puts("Wrong password sorry, exiting.");print("Find: 0x%x" % FIND)print("Avoid: 0x%x" % AVOID)
password = claripy.BVS('password', 8 * 16)state = proj.factory.entry_state(args=[BINARY, OUTFILE], stdin=password)simgr = proj.factory.simulation_manager(state)simgr.explore(find=FIND, avoid=AVOID)
print(simgr.found[0].posix.dumps(0))print(time.time() - t, "seconds")```
```kali@kali:~/Downloads/secure_db$ ./solve.py ERROR   | 2020-05-09 17:06:30,010 | cle.backends.elf.elf | PyReadELF couldn't load this file. Trying again without section headers...                                                                   <Arch X86 (LE)>./secure_dbEntry: 0x8048970Find: 0x80488d6Avoid: 0x804890aWARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.                 WARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:             WARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | 1) setting a value to the initial state                                                                                        WARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null                       WARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY_REGISTERS}, to suppress these messages.                           WARNING | 2020-05-09 17:06:30,327 | angr.state_plugins.symbolic_memory | Filling register edi with 4 unconstrained bytes referenced from 0x804a3f1 (PLT.close+0x1d11 in secure_db (0x804a3f1))          b'T4h7s_4ll_F0lks\x00'175.94404363632202 seconds```
That's pretty freakin' incredible. This was my first time using angr, and it could have saved me hours on previous CTF challenges like this.
Now that we have the password, pass it into `secure_db`.
```kali@kali:~/Downloads/secure_db$ echo 'T4h7s_4ll_F0lks' > passkali@kali:~/Downloads/secure_db$ ./secure_db out.db < passHi Doge ! ░░░░░░░░░▄░░░░░░░░░░░░░░▄░░░░░░░░░░░░▌▒█░░░░░░░░░░░▄▀▒▌░░░░░░░░░░░▌▒▒█░░░░░░░░▄▀▒▒▒▐░░░░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐░░░░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐░░░░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌░░░░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒▌░░░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐░░░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄▌░░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▌░▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒▐░▐▒▒▐▀▐▀▒░▄▄▒▄▒▒▒▒▒▒░▒░▒░▒▒▒▒▌▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐░░▌▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒░▒░▒░▒░▒▒▒▌░░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐░░░░▀▄▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▄▒▒▒▒▌░░░░░░▀▄▒▒▒▒▒▒▒▒▒▒▄▄▄▀▒▒▒▒▄▀░░░░░░░░░▀▄▄▄▄▄▄▀▀▀▒▒▒▒▒▄▄▀░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▀▀░░░░░░░░Please input the password :-> okThe password is valid.Contacting serverRetrieving to DB, decrypting it using your password.File downloaded. 32768 bytes.Done. Check your output file.Received and *hopefully* sucessfuly decrypted the database with the given password.```
Now that we have the file, we can see that it is a SQLite DB. It's small, so running `.dump` is an easy way to find where the flag is.
```kali@kali:~/Downloads/secure_db$ file out.db out.db: SQLite 3.x database, last written using SQLite version 3022000kali@kali:~/Downloads/secure_db$ sqlite3 out.dbSQLite version 3.31.0 2019-12-29 00:52:41Enter ".help" for usage hints.sqlite> .dump...sqlite> select * from flag;shkCTF{p4ssw0rd_pr0t3ct3d_db_6a773d0fcb5d742603167d2958547914}```
