# C6: Gates of hell
- Category: Reverse- URL: <https://squarectf.com/2018/gates_of_hell.html>
## Description
```C6: gates of hell
C6 is a Linux based system. It was brought to Charvis by the very first settlers. You found a USB drive with a copy of the executable.
Now, all you need to do is figure out the correct input to disable C6 through its online interface.```
This is one of the more interesting challenge I have tried so far. Briefly, we can use GDB to deduce and determine the program flow and logic. It sure is troublesome but I have solved it by hand. I will continue to think about an easier way to solve it rather than manually. So, lets get going.
---
![gateschallenge.PNG](gateschallenge.PNG)
## Beginning
First, the type of file was determined to make sure that it is not packed or anything like that.
```bash$ file gates-of-hellgates-of-hell: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped```
We can see that the file had been stripped removing valuable information and also it has been statically linked which does not allow one to easily determine what functions had been used here.
Lets try to run the program to look for any interactions.
```root@kali:~/Desktop# ./gates-of-hellroot@kali:~/Desktop# ./gates-of-hell asdroot@kali:~/Desktop# ./gates-of-hell asd asdasdasroot@kali:~/Desktop# ./gates-of-hell asd asdasdas asdasdaroot@kali:~/Desktop# ./gates-of-hell asd asdasdas asdasdaroot@kali:~/Desktop# ./gates-of-hell asd asdasdas asdasda asd asdasdas asdasda asd asdasdas asdasda asd asdasdas asdasda```
There did not seem to have much going on outwardly.
So let's fire up out gdb to see what is happening.
```gdb-peda$ file gates-of-hellReading symbols from gates-of-hell...(no debugging symbols found)...done.gdb-peda$ info filesSymbols from "/root/Desktop/gates-of-hell".Local exec file:	`/root/Desktop/gates-of-hell', file type elf32-i386.	Entry point: 0x8048060	0x08048060 - 0x0804820e is .textgdb-peda$ break *0x8048060Breakpoint 1 at 0x8048060gdb-peda$ run.........Breakpoint 1, 0x08048060 in ?? ()gdb-peda$ x/200i $pc=> 0x8048060:	pop    eax   0x8048061:	cmp    eax,0x10   0x8048064:	jle    0x80480c3   0x8048066:	add    esp,0x4   0x8048069:	mov    ecx,0x10   0x804806e:	mov    ebx,0x25   0x8048073:	pop    esi   0x8048074:	push   ecx   0x8048075:	push   ebx   0x8048076:	call   0x80481ca   0x804807b:	pop    ebx   0x804807c:	push   eax   0x804807d:	aam    0x12   0x804807f:	aad    0xf6   0x8048081:	pop    eax   0x8048082:	jns    0x8048086   0x8048084:	xor    ebx,ebx   0x8048086:	mov    al,BYTE PTR [eax+0x80480ca]   0x804808c:	xor    edx,edx   0x804808e:	mul    ebx   0x8048090:	mov    ebx,eax   0x8048092:	mov    ecx,0x100   0x8048097:	mov    al,BYTE PTR [ecx+0x80480c9]   0x804809d:	dec    al   0x804809f:	js     0x80480a7   0x80480a1:	mov    BYTE PTR [ecx+0x80480c9],al   0x80480a7:	loop   0x8048097   0x80480a9:	pop    ecx   0x80480aa:	loop   0x8048073   0x80480ac:	cmp    ebx,0x29a   0x80480b2:	jne    0x80480c3   0x80480b4:	mov    ecx,0x80481f0   0x80480b9:	mov    edx,0x17   0x80480be:	call   0x80481e3   0x80480c3:	mov    eax,0x1   0x80480c8:	int    0x80.....
```
The program ends here at address 0x80480c8 since it is a syscall to exit. note that EAX was given value of one which signifies an exit. There are also no jumps that jumps out of this address so I have made this assumption.
---
## Quick static analysis
There are quite a few commands that are really unfamiliar to me. They are loop, aam and aam. Aside from that, lets scan through the program.
There are two loops being used here as we can see in the opcode, `loop`. After some reading up, loop here uses ECX as counter variable and will be decremented after each iterations.
It seems also that there are some array manipulation going on as well.
```   0x8048086:	mov    al,BYTE PTR [eax+0x80480ca]   ....   ....   ....   0x8048092:	mov    ecx,0x100   0x8048097:	mov    al,BYTE PTR [ecx+0x80480c9]   ...   ...   0x80480a1:	mov    BYTE PTR [ecx+0x80480c9],al
```
Also it has a relatively large chunk of data stored in the array since there are value 256 in ECX and this ECX is also being used as counter for the loop opcode. This suggests that in this loop, something is done to each element as though there are some sort of adjustments being done.
For this program, we win if and only if we can get the value 666 to be stored in EBX at the end of all the processing.
```    0x80480ac:	cmp    ebx,0x29a```
The thing that is controlling ebx in this context is the multiplication of EAX with EBX and later storing the result in EAX.
```    0x804808e:	mul    ebx    0x8048090:	mov    ebx,eax```
There is also a catch; There is a way to mess up the storage of numbers in this register. That is after two operations aam and aad check if the Sign Flag has been set. If it is set then ebx is stored as 0 which is trouble since any number multiplied by 0 is 0. This means EBX will be 0 as long as the sign flag is set even once.
```0x804807d:	aam    0x12   0x804807f:	aad    0xf6   0x8048081:	pop    eax   0x8048082:	jns    0x8048086        # Jump if not sign else   0x8048084:	xor    ebx,ebx          # set EBX to 0........```
These are the opertions that occurs when these instructions are executed.We can read more about [aad from here](http://qcd.phys.cmu.edu/QCDcluster/intel/vtune/reference/vc3a.htm) and [aam from here](http://qcd.phys.cmu.edu/QCDcluster/intel/vtune/reference/vc4a.htm).
```aam 0x12
    AL -->  AL % 18    AH --> AL / 18
aad 0x0f6
    AL --> (AH *  246) + AL    AH --> 0```
Sign flag is being set if AL has 1 in the Most Significant Bit. For example, 0xF3 in resultant AL will result in Sign Flag being set while 0x73 will not. Another note worth noting is that the EAX registers that the operation will occur on is from a function which will be use to multiply to ebx which we need it to be of value 666.
While it is hard to explain all the details here, I have written a pseudocode of the program.
```cint *temp = argumentList;
// Make sure to have at least 16 arguments though program will terminate at 16if(argc > 16){    int x = 16;    int y = 37;
    do{        oneInput = temp ;        temp = &x;
        index = function1(oneInput);
        // A constraint ia found here        __asm{            aam 0x12            // eax from function1 is being operated on            aad 0x0F6        }
        z = index ;
        // A line we want to skip at all cost.        if (SF == 1) y = 0;
        // z is what we want to multiply to y for comparison with value        z = array_at_80480CA [ index ] ;        y *= z ;        i = 256 ;        do{        k = array_at_0x80480CA[ i - 1 ] - 1 ; // Same as array_at_0x0x80480C9[ i ]
        /* If current element is not less than 0, decrement and store to         the current element location else just ignore*/        if ( k >= 0 ){            array_at_0x80480CA[ i - 1 ] = k ; // Same as array_at_0x0x80480C9[ i ]            --i ;        }          } while (i) ;
        x = temp - 1;   // on to the next argument    } while (  temp != 1 ); // while 16 arguments are not being iterated through    if( y == 666 ){    printf("flag is here on server");    }    exit();}```
Lets take a look at function1 ( located at 0x80481ca ),
```   0x8048073:	pop    esi   0x8048074:	push   ecx   0x8048075:	push   ebx      # Stores EBX result on stack since it will                                # be used in the function 0x80481ca   0x8048076:	call   0x80481ca```
Examining function1,
```gdb-peda$ x/200i $pc   0x80481ce:	mov    dl,BYTE PTR [esi]   0x80481d0:	inc    esi   0x80481d1:	sub    dl,0x30   0x80481d4:	cmp    dl,0x39   0x80481d7:	ja     0x80481e2   0x80481d9:	mul    bl   0x80481db:	add    al,dl   0x80481dd:	call   0x80481ce   # Calls itself again   0x80481e2:	ret   0x80481e3:	mov    eax,0x4   0x80481e8:	mov    ebx,0x1   0x80481ed:	int    0x80   0x80481ef:	ret```
There is another constraint being found here. ESI register here contain the argument that you have added. This function will be called 16 times thanks to the loop command with parameter as the input argument.
The ASCII value of the argument is then subtracted by 48 and then compared to see if the result is less than 57. If the number is less than 57 then recursion occurs by calling itself by At first it looks impossible however these are a byte which means they have just 8 bits and it is possible to overflow the 8 bit space. For example: 0x29 - 0x30 = 0xF9 which gives a number greater than 57 and thus breaks out of the recursion.
Pseudocode looks something like this
```c
char function1( char *argumentX){
    char d = *argumentX;    char a = 0;    argumentX++;        // Goes down the string in the argument    char compare = d - 48;    if(compare <= 57){        result = function1(argumentX);   // Go to the next character    }    return result;      // This is the index will be pointed to the array chunk}```
For my case, I used all single characters as argument followed by a space. This is so that there will be value 0x00 after every argument which allows for the overflow.
---
## Solution
Firstly, there are too many ASCII to try out one by one therefore with the constraints found, we can try to reduce the possibilities and narrow to a smaller group of possible arguments.
We can deal with the aam and aad instructions.
aam refers to Adjust AX after Multiplication and aad refers to Adjust AX After Division.
```aam 0x12    AL -->  AL % 18    AH --> AL / 18
aad 0x0f6
    AL --> (AH *  246) + AL    AH --> 0```
Since aam occurs before aad, we can formulate a constraint equation and try it for ASCII value from 0 to 255 such that the resultant AL value is smaller than 0x7F and larger than 0.
```aam 18
    X         Y             INITIAL_____________________|_________|_________|   Y/18       Y%18          RESULT
aad 246    A          B        INITIAL_____________________|_________|_________|
    0000   A*246 + B       RESULT
Since we know A = Y/18 and B = Y%18, we can substitute into the result after aad 246.
we get:    AL = Y/18*246 + Y%18       = Y%18 - 10/18*Y         # Because it is a signed number and 247 is actually -10
Remember that we do not want this value to be signed. This means AL < 127 and AL > 0.```
For this purpose of checking what are the possible values to be used, we can write a short python script.
```pythonfor i in range(0,255):    x = i%18-i/18*10    if x < 0x7f and x > 0:   	 # The reason we add 0x30 is because i will be subtracted by 0x30 so we need to add it back for the POSSIBLE CHARACTER   	 print("ASCII : "+str(i+0x30)+" from "+str(i)+", Possible Character : " + chr(i+0x30))```
This prints the ASCII arguments that can be used and will not violate the constraint of a signed AL. The result is as folllows
```ASCII : 49 from 1, Possible Character : 1ASCII : 50 from 2, Possible Character : 2ASCII : 51 from 3, Possible Character : 3ASCII : 52 from 4, Possible Character : 4ASCII : 53 from 5, Possible Character : 5ASCII : 54 from 6, Possible Character : 6ASCII : 55 from 7, Possible Character : 7ASCII : 56 from 8, Possible Character : 8ASCII : 57 from 9, Possible Character : 9ASCII : 58 from 10, Possible Character : :ASCII : 59 from 11, Possible Character : ;  # TO BE DELETEDASCII : 60 from 12, Possible Character : <  # TO BE DELETEDASCII : 61 from 13, Possible Character : =ASCII : 62 from 14, Possible Character : >  # TO BE DELETEDASCII : 63 from 15, Possible Character : ?ASCII : 64 from 16, Possible Character : @ASCII : 65 from 17, Possible Character : AASCII : 77 from 29, Possible Character : MASCII : 78 from 30, Possible Character : NASCII : 79 from 31, Possible Character : OASCII : 80 from 32, Possible Character : PASCII : 81 from 33, Possible Character : QASCII : 82 from 34, Possible Character : RASCII : 83 from 35, Possible Character : S```
The comment TO BE DELETED is because if it is a special character in the bash command for us to test it out.
#### The long array
There is a loop section for 256 times.
```c......        do{        k = array_at_0x80480CA[ i - 1 ] - 1 ; // Same as array_at_0x0x80480C9[ i ]
        /* If current element is not less than 0, decrement and store to         the current element location else just ignore*/        if ( k >= 0 ){            array_at_0x80480CA[ i - 1 ] = k ; // Same as array_at_0x0x80480C9[ i ]            --i ;        }          } while (i) ;......```
What this effectively does is that in the first iteration, it will traverse starting from the end of the array down to the first and decrement the element's value if the element is not already 0x00, then in the next iteration, traverse from the last second element to the first and decrement value if not already 0x00 and so on till it reaches the first element in the array.
```Example : LOOP FOR 4 TIMES
Initial
0x5 0x3 0x3 0x2
First Iteration    0x4 0x2 0x2 0x1
Second iteration    0x3 0x1 0x1 0x1
Third Iteration    0x2 0x0 0x1 0x1
Last iteration    0x1 0x0 0x1 0x1```
This means for every iteration, changes to element are made and so we have to account for that.
To view the whole array, we know that the array of interest is in `0x80480CA`.
```gdb-peda$ x/256bx 0x80480ca0x80480ca:	0x05	0x09	0x04	0x0f	0x05	0x0b	0x10	0x0e0x80480d2:	0x0b	0x0d	0x0d	0x08	0x0c	0x07	0x10	0x020x80480da:	0x06	0x04	0x0b	0x04	0x02	0x0d	0x07	0x0a0x80480e2:	0x04	0x0c	0x0e	0x10	0x07	0x06	0x03	0x0e0x80480ea:	0x01	0x09	0x01	0x0c	0x0e	0x0a	0x0b	0x050x80480f2:	0x01	0x09	0x08	0x0d	0x06	0x02	0x10	0x060x80480fa:	0x06	0x02	0x03	0x06	0x0b	0x0e	0x05	0x050x8048102:	0x03	0x0f	0x01	0x05	0x07	0x0d	0x08	0x050x804810a:	0x0c	0x10	0x01	0x02	0x08	0x04	0x0c	0x050x8048112:	0x0b	0x0d	0x0d	0x08	0x09	0x03	0x09	0x0a0x804811a:	0x0c	0x10	0x0b	0x06	0x06	0x0d	0x02	0x0e0x8048122:	0x0d	0x0e	0x03	0x04	0x01	0x06	0x0c	0x0e0x804812a:	0x05	0x09	0x01	0x04	0x08	0x04	0x07	0x060x8048132:	0x0c	0x05	0x05	0x03	0x03	0x0d	0x0b	0x0c0x804813a:	0x05	0x01	0x04	0x02	0x03	0x0f	0x0b	0x100x8048142:	0x01	0x02	0x02	0x04	0x0c	0x05	0x0a	0x060x804814a:	0x0e	0x02	0x05	0x0f	0x0d	0x0d	0x0a	0x0f0x8048152:	0x07	0x08	0x0e	0x06	0x0a	0x0b	0x05	0x0a0x804815a:	0x01	0x0c	0x0a	0x0a	0x07	0x07	0x10	0x080x8048162:	0x09	0x08	0x0b	0x0c	0x0a	0x10	0x0f	0x090x804816a:	0x10	0x10	0x0c	0x02	0x07	0x01	0x0f	0x060x8048172:	0x04	0x03	0x08	0x0b	0x0d	0x07	0x03	0x050x804817a:	0x10	0x04	0x0b	0x09	0x0c	0x02	0x0d	0x010x8048182:	0x0c	0x05	0x0b	0x0b	0x09	0x0f	0x04	0x100x804818a:	0x08	0x0b	0x07	0x07	0x07	0x08	0x0c	0x020x8048192:	0x07	0x04	0x06	0x04	0x0f	0x05	0x01	0x040x804819a:	0x07	0x04	0x04	0x03	0x0a	0x07	0x0c	0x0f0x80481a2:	0x07	0x0c	0x01	0x0e	0x04	0x04	0x0b	0x010x80481aa:	0x0f	0x0e	0x09	0x0e	0x10	0x02	0x04	0x0c0x80481b2:	0x02	0x0f	0x0f	0x03	0x04	0x09	0x08	0x0f0x80481ba:	0x10	0x03	0x0e	0x0d	0x04	0x03	0x02	0x010x80481c2:	0x09	0x0c	0x01	0x07	0x02	0x0a	0x08	0x0a```
I was thinking for a really long time also because this is where value is being picked to be mulitplied to EBX to get 666. So I broke it down to 666 = 3 x 3 x 2 x 37 but 37 is a prime number and we cant find it anywhere here. After thinking and looking around, i realised 37 was already given from the start.
```   0x804806e:	mov    ebx,0x25   #37```
This was perfect. So the problem now is to get the index which will be chosen by function1 since function1 chooses the index of what value to multiply to EBX and our input determines which index get chosen.
#### BRIEF PROGRAM FLOW
```for each of the 16 arguments:    function1 chooses index based on argument    if index is signed        break    EBX will be multiplied by array[index]    alter array
Check if EBX = 666```
This shows that our input argument is mapped to certain numbers which we will eventually want to map it to
```37    *1*3*1*1*1*1*1*2*1*3*1*1*1*1*1*1
It is in such strange order because there are some index that are out of possible range as the array alter at the time of solving it.```
The problem for checking sign is dealt with as long as we choose a possible value.We have to keep track of the changes in the array such that as we traverse down the arguments we input, we have to remember the state of the array.
For this challenge, I had done it manually by comparing the values that I want with the initial array state.
### FIRST VALUE
For the FIRST value to multiply 37 is 1.So we first want to find the index where it is located in the array.
```0x80480ca:	0x05	0x09	0x04	0x0f	0x05	0x0b	0x10	0x0e0x80480d2:	0x0b	0x0d	0x0d	0x08	0x0c	0x07	0x10	0x020x80480da:	0x06	0x04	0x0b	0x04	0x02	0x0d	0x07	0x0a0x80480e2:	0x04	0x0c	0x0e	0x10	0x07	0x06	0x03	0x0e0x80480ea:	0x01```
Here the index is 0x80480ea - 0x80480ca = 32.Remember that in function1, we subtract 48 or 0x30. This means we need to add it to get ASCII value to get 80 to get character 'P'.Now we check if it is a subset of the possible range and yes it is!
```..ASCII : 79 from 31, Possible Character : OASCII : 80 from 32, Possible Character : PASCII : 81 from 33, Possible Character : Q..```
Also the current state of the array is intial, we do not add anything.
Checking with GDB
```gdb-peda$ set args P A A A A A A A A A A A A A A A A A A AA A A A
...[----------------------------------registers-----------------------------------]EAX: 0x1                        <----------------------- HERE IS THE TARGET VALUEEBX: 0x25 ('%')ECX: 0x10EDX: 0xd0ESI: 0xffffd594 --> 0x410041 ('A')EDI: 0x0EBP: 0x0ESP: 0xffffd398 --> 0x10EIP: 0x804808c --> 0xe3f7d231EFLAGS: 0x213 (CARRY parity ADJUST zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]   0x8048082:	jns    0x8048086   0x8048084:	xor    ebx,ebx   0x8048086:	mov    al,BYTE PTR [eax+0x80480ca]=> 0x804808c:	xor    edx,edx   0x804808e:	mul    ebx
...
```
Here we get EAX = 0x1 as what we want which we will then multiply with EBX and later stored in EBX; i.e. 37\*1
We can justify that by stepping a few lines
```[----------------------------------registers-----------------------------------]EAX: 0x25 ('%')EBX: 0x25 ('%')                <----------------- HERE IS THE RESULT OF 37*1ECX: 0x10EDX: 0x0ESI: 0xffffd594 --> 0x410041 ('A')EDI: 0x0EBP: 0x0ESP: 0xffffd398 --> 0x10EIP: 0x8048092 --> 0x100b9EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]   0x804808c:	xor    edx,edx   0x804808e:	mul    ebx   0x8048090:	mov    ebx,eax=> 0x8048092:	mov    ecx,0x100   0x8048097:	mov    al,BYTE PTR [ecx+0x80480c9]
```
### SECOND VALUE
Second value from `37 *1*3*1*1*1*1*1*2*1*3*1*1*1*1*1*1` is 3.
Looking up the intial table we get
```0x80480ca:	0x05	0x09	0x04	0x0f	0x05	0x0b	0x10	0x0e0x80480d2:	0x0b	0x0d	0x0d	0x08	0x0c	0x07	0x10	0x020x80480da:	0x06	0x04	0x0b	0x04	0x02	0x0d	0x07	0x0a0x80480e2:	0x04	0x0c	0x0e	0x10	0x07	0x06	0x03```
Here our values in the table will be decremented by 1. Since we are only interested in elements really close to the start and only for 16 iterations, we wont be affected by the elements near the end not changing.
We need to remember to mentally add the value 1 since it is in the next position of the input arguments. Since we are interested in value 3 (to be multiplied to EBX), we add 3 to 1 = 4 and start searching for 0x4 in the table which we can see in the index 2.
Adding 48 to 2 to give 50 which is also part of the possible character 2.
```ASCII : 49 from 1, Possible Character : 1ASCII : 50 from 2, Possible Character : 2ASCII : 51 from 3, Possible Character : 3..```
Thus our second argument is 2
Testing it out on GDB
```gdb-peda$ b *0x804808cgdb-peda$ set args P 2 A A A A  A A A A A A A A A A  AA
...
EAX: 0x3                           <------------- THE 0x3 WE WANTEDEBX: 0x25 ('%')ECX: 0xfEDX: 0xd0ESI: 0xffffd59b --> 0x410041 ('A')EDI: 0x0EBP: 0x0ESP: 0xffffd3ac --> 0xfEIP: 0x804808c --> 0xe3f7d231EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]   0x8048082:	jns    0x8048086   0x8048084:	xor    ebx,ebx   0x8048086:	mov    al,BYTE PTR [eax+0x80480ca]=> 0x804808c:	xor    edx,edx   0x804808e:	mul    ebx
gdb-peda$ ni..gdb-peda$ ni..gdb-peda$ ni..gdb-peda$ ni
[----------------------------------registers-----------------------------------]EAX: 0x6f ('o')EBX: 0x6f ('o')         <------------0x6f = 111 which is 37*3 which is  correctECX: 0xfEDX: 0x0ESI: 0xffffd59b --> 0x410041 ('A')EDI: 0x0EBP: 0x0ESP: 0xffffd3ac --> 0xfEIP: 0x8048092 --> 0x100b9EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]   0x804808c:	xor    edx,edx   0x804808e:	mul    ebx   0x8048090:	mov    ebx,eax=> 0x8048092:	mov    ecx,0x100...```
As we carry on ...
```    37     Iteration  Find          Index    ASCII_Value   Character    -----------------------------------------------------------------------    *1          0      1+0=1         32        48+32=80        P
    *3          1      3+1=4          2        48+2=50         2
    *1          2      1+2=3          30       48+30=78        N
    *1          3      3+1=4          2        48+2=50         2
    *1          4      1+4=5          4        48+4=52         4
    *1          5      1+5=6          16       48+16=64        @
    *1          6      1+6=7          13       48+13=61        =
    *2          7      2+7=9          1        48+1=49         1
    *1          8      1+8=9          1        48+1=19         1
    *3          9      3+9=0xc        35       48+35=83        S
    *1          10     1+10=0xb       5        48+5=53         5
    *1          11     1+11=0xc       35       48+35=83        S
    *1          12     1+12=0xd       9        48+9=57         9
    *1          13     1+13=0xe       7        48+7=55         7
    *1          14     1+14=0xf       3        48+3=51         3
    *1          15     1+15=0x10      6        48+6=54         6```
We can now test the program with the found charactersP 2 N 2 4 @ = 1 1 S 5 S 9 7 3 6
```root@kali:~/Desktop# ./gates-of-hell  P 2 N 2 4 @ = 1 1 S 5 S 9 7 3 6flag is here on server```
PERFECT!!
Now we can go on to submit through the "online interface". There is no where for us to submit the flag though it look like a terminal.
![gatesonlineinterface.PNG](gatesonlineinterface.PNG)The strange thing in the URL is that it seems to be a perl file. It is almost as though we can run a program with the URL. So I tried ?file=/bin/gates-of-hell.
![gatesfile.PNG](gatesfile.PNG)
We can see that it seems to append behind then only did i realise that the command line is waiting for input. Since the string `P 2 N 2 4 @ = 1 1 S 5 S 9 7 3 6` has to be used as part of URL, we have to encode it.
After encoding, we get
```P%202%20N%202%204%20%40%20%3D%201%201%20S%205%20S%209%207%203%206```
Now all we need to do is to prepend a question mark and append the whole string behind the url.
```https://thawing-garden-44258.squarectf.com/cgi-bin/gates-of-hell.pl?P%202%20N%202%204%20%40%20%3D%201%201%20S%205%20S%209%207%203%206```
![gatesflag.PNG](gatesflag.PNG)
And VOILA! THE FLAG IS PRESENTED TO US!!!!!!!!!!!!!!!!!!
```flag-526f64696e0000666```