HackTheBox – Pseudo

In this write-up we will be visiting the Pseudo challenge from HackTheBox.

Do you have enough permissions to get the flag?


We start by running strings on the binary to look for low-hanging fruits. Interestingly, we find a string that suggests that the binary is packed using the UPX packer, as shown in the illustration below. Note that I used grep to filter the UPX string in order to reduce the output of the command.

Interestingly for us, the UPX packer is an open-source project which is freely available for anyone interested and contains a supported unpacking feature built into the upx binary. We can thus use upx itself to unpack the binary as shown below.

Now that the binary has been unpacked, we can go ahead and open it in IDA for further analysis.

In the main function we find that the executable loads a buffer into the X21 register, initiates the X20 register to 0 and reads a byte from the loaded buffer in register X21.

The byte read from the X21 register is then compared to a series of values, and upon matching, execution flow is redirected to the respective handler. All handlers terminate by returning to 0x400570, after which the X20 register is incremented and a new byte is read from the X21 buffer, using X20 as an offset.

We can thus conclude that the application is a sort of interpreter, that will perform a series of actions based on a predefined list of handlers to execute. We can now go ahead and analyze the individual handlers to figure out which actions they are each responsible for carrying out.


Handler 0x17 – Increment pointer

.text:0000000000400584 A1 0B 00 90                 ADRP            X1, #off_5740C8@PAGE
.text:000000000040058C 20 64 40 F9                 LDR             X0, [X1,#off_5740C8@PAGEOFF]
.text:0000000000400590 00 04 00 91                 ADD             X0, X0, #1
.text:0000000000400594 20 64 00 F9                 STR             X0, [X1,#off_5740C8@PAGEOFF]

This handler appears to increment the instruction pointer, equivalent to the following C code.

++off_5740C8;

Handler 0x23 – Decrement pointer

.text:00000000004005D0 A1 0B 00 90                 ADRP            X1, #off_5740C8@PAGE
.text:00000000004005D4 20 64 40 F9                 LDR             X0, [X1,#off_5740C8@PAGEOFF]
.text:00000000004005D8 00 04 00 D1                 SUB             X0, X0, #1
.text:00000000004005DC 20 64 00 F9                 STR             X0, [X1,#off_5740C8@PAGEOFF]

This handler appears to decrement the instruction pointer, equivalent to the following C code.

--off_5740C8;

Handler 0x0e – Increment pointer data

.text:00000000004005E8 A0 0B 00 90                 ADRP            X0, #off_5740C8@PAGE
.text:00000000004005EC 01 64 40 F9                 LDR             X1, [X0,#off_5740C8@PAGEOFF]
.text:00000000004005F0 20 00 40 39                 LDRB            W0, [X1]
.text:00000000004005F4 00 04 00 11                 ADD             W0, W0, #1
.text:00000000004005F8 20 00 00 39                 STRB            W0, [X1]

This handler appears to increment the instruction pointer data, equivalent to the following C code.

++*off_5740C8;

Handler 0x01 – Decrement pointer data

.text:0000000000400600 A0 0B 00 90                 ADRP            X0, #off_5740C8@PAGE
.text:0000000000400604 01 64 40 F9                 LDR             X1, [X0,#off_5740C8@PAGEOFF]
.text:0000000000400608 20 00 40 39                 LDRB            W0, [X1]
.text:000000000040060C 00 04 00 51                 SUB             W0, W0, #1
.text:0000000000400610 20 00 00 39                 STRB            W0, [X1]

This handler appears to decrement the instruction pointer data, equivalent to the following C code.

--*off_5740C8;

Handler 0x05 – Output pointer data

.text:0000000000400618 A0 0B 00 90                 ADRP            X0, #off_5740C8@PAGE
.text:000000000040061C 00 64 40 F9                 LDR             X0, [X0,#off_5740C8@PAGEOFF]
.text:0000000000400620 13 00 40 39                 LDRB            W19, [X0]
.text:0000000000400624 E0 03 13 2A                 MOV             W0, W19
.text:0000000000400628 A4 79 02 94                 BL              sub_49ECB8
.text:000000000040062C 1F 00 00 71                 CMP             W0, #0
.text:0000000000400630 64 0A 4A 7A                 CCMP            W19, #0xA, #4, EQ
.text:0000000000400634 01 2C 00 54                 B.NE            loc_400BB4
.text:0000000000400638 81 0B 00 F0                 ADRP            X1, #off_573A68@PAGE
.text:000000000040063C E0 03 13 2A                 MOV             W0, W19
.text:0000000000400640 21 34 45 F9                 LDR             X1, [X1,#off_573A68@PAGEOFF]
.text:0000000000400644 21 00 40 F9                 LDR             X1, [X1] ; dword_574560
.text:0000000000400648 CA C3 02 94                 BL              sub_4B1570

This handler appears to output the instruction pointer data, equivalent to the following C code.

if (*off_5740C8 != '\n')
    putchar(*off_5740C8);
else
    return 1;

Handler 0x80 – Read input password

.text:0000000000400650 B3 0B 00 90                 ADRP            X19, #off_5740C8@PAGE
.text:0000000000400654 A2 01 80 52                 MOV             W2, #0xD
.text:0000000000400658 61 22 03 91                 ADD             X1, X19, #off_5740C8@PAGEOFF
.text:000000000040065C 96 0B 00 F0                 ADRP            X22, #off_573E28@PAGE
.text:0000000000400660 63 66 40 F9                 LDR             X3, [X19,#off_5740C8@PAGEOFF]
.text:0000000000400664 20 04 40 F9                 LDR             X0, [X1,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:0000000000400668 23 04 00 F9                 STR             X3, [X1,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:000000000040066C 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:0000000000400670 D6 16 47 F9                 LDR             X22, [X22,#off_573E28@PAGEOFF]
.text:0000000000400674 02 00 00 39                 STRB            W2, [X0]
.text:0000000000400678 60 66 40 F9                 LDR             X0, [X19,#off_5740C8@PAGEOFF]
.text:000000000040067C 00 04 00 91                 ADD             X0, X0, #1
.text:0000000000400680 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:0000000000400684
.text:0000000000400684             loc_400684                              ; CODE XREF: sub_4004B0+200↓j
.text:0000000000400684 C0 02 40 F9                 LDR             X0, [X22] ; unk_574778
.text:0000000000400688 64 C3 02 94                 BL              sub_4B1418
.text:000000000040068C 00 1C 00 53                 UXTB            W0, W0
.text:0000000000400690 61 66 40 F9                 LDR             X1, [X19,#off_5740C8@PAGEOFF]
.text:0000000000400694 02 78 01 51                 SUB             W2, W0, #0x5E
.text:0000000000400698 1F 28 00 71                 CMP             W0, #0xA
.text:000000000040069C 63 22 03 91                 ADD             X3, X19, #off_5740C8@PAGEOFF
.text:00000000004006A0 22 00 00 39                 STRB            W2, [X1]
.text:00000000004006A4 60 66 40 F9                 LDR             X0, [X19,#off_5740C8@PAGEOFF]
.text:00000000004006A8 00 04 00 91                 ADD             X0, X0, #1
.text:00000000004006AC 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:00000000004006B0 A1 FE FF 54                 B.NE            loc_400684
.text:00000000004006B4 61 04 40 F9                 LDR             X1, [X3,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:00000000004006B8 61 00 00 A9                 STP             X1, X0, [X3]

This handler appears to read a decremented input string to the password buffer, equivalent to the following C code.

*off_5740D0++ = '\r';

do
{
    char c = getchar();
    *off_5740D0++ = c - 0x5e;
}
while (c != '\n');

Handler 0xef – Fetch username

.text:0000000000400968 A0 00 80 D2                 MOV             X0, #5
.text:000000000040096C 13 00 80 D2                 MOV             X19, #0
.text:0000000000400970 6A EB 02 94                 BL              sub_4BB718
.text:0000000000400974 F6 03 00 AA                 MOV             X22, X0
.text:0000000000400978
.text:0000000000400978             loc_400978                              ; CODE XREF: sub_4004B0+5B4↓j
.text:0000000000400978 68 02 62 1E                 SCVTF           D8, W19
.text:000000000040097C 01 90 64 1E                 FMOV            D1, #10.0
.text:0000000000400980 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400984 47 45 02 94                 BL              loc_491EA0
.text:0000000000400988 0E 40 60 1E                 FMOV            D14, D0
.text:000000000040098C 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400990 01 50 64 1E                 FMOV            D1, #9.0
.text:0000000000400994 43 45 02 94                 BL              loc_491EA0
.text:0000000000400998 0F 40 60 1E                 FMOV            D15, D0
.text:000000000040099C 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009A0 01 10 64 1E                 FMOV            D1, #8.0
.text:00000000004009A4 3F 45 02 94                 BL              loc_491EA0
.text:00000000004009A8 0D 40 60 1E                 FMOV            D13, D0
.text:00000000004009AC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009B0 01 90 63 1E                 FMOV            D1, #7.0
.text:00000000004009B4 3B 45 02 94                 BL              loc_491EA0
.text:00000000004009B8 0C 40 60 1E                 FMOV            D12, D0
.text:00000000004009BC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009C0 01 10 63 1E                 FMOV            D1, #6.0
.text:00000000004009C4 37 45 02 94                 BL              loc_491EA0
.text:00000000004009C8 0B 40 60 1E                 FMOV            D11, D0
.text:00000000004009CC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009D0 01 90 62 1E                 FMOV            D1, #5.0
.text:00000000004009D4 33 45 02 94                 BL              loc_491EA0
.text:00000000004009D8 0A 40 60 1E                 FMOV            D10, D0
.text:00000000004009DC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009E0 01 10 62 1E                 FMOV            D1, #4.0
.text:00000000004009E4 2F 45 02 94                 BL              loc_491EA0
.text:00000000004009E8 09 40 60 1E                 FMOV            D9, D0
.text:00000000004009EC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004009F0 01 10 61 1E                 FMOV            D1, #3.0
.text:00000000004009F4 2B 45 02 94                 BL              loc_491EA0
.text:00000000004009F8 81 0E 00 5C                 LDR             D1, =0xBF40094F743C5109
.text:00000000004009FC EF 09 61 1E                 FMUL            D15, D15, D1
.text:0000000000400A00 81 0E 00 5C                 LDR             D1, =0xBF27D85FD39AF2BA
.text:0000000000400A04 CE 3D 41 1F                 FMADD           D14, D14, D1, D15
.text:0000000000400A08 81 0E 00 5C                 LDR             D1, =0xBF4A783E719D1A9B
.text:0000000000400A0C AD 39 41 1F                 FMADD           D13, D13, D1, D14
.text:0000000000400A10 81 0E 00 5C                 LDR             D1, =0x3F5FB6759FFFB21D
.text:0000000000400A14 8C 35 41 1F                 FMADD           D12, D12, D1, D13
.text:0000000000400A18 81 0E 00 5C                 LDR             D1, =0x3F9C779DE2485B1C
.text:0000000000400A1C 6B 31 41 1F                 FMADD           D11, D11, D1, D12
.text:0000000000400A20 81 0E 00 5C                 LDR             D1, =0x3FC4D717D3D16BA7
.text:0000000000400A24 4A 2D 41 1F                 FMADD           D10, D10, D1, D11
.text:0000000000400A28 81 0E 00 5C                 LDR             D1, =0x3FE1ED5929D7C65E
.text:0000000000400A2C 29 29 41 1F                 FMADD           D9, D9, D1, D10
.text:0000000000400A30 81 0E 00 5C                 LDR             D1, =0xBFADCEEF3B8660AA
.text:0000000000400A34 09 24 41 1F                 FMADD           D9, D0, D1, D9
.text:0000000000400A38 00 09 68 1E                 FMUL            D0, D8, D8
.text:0000000000400A3C 61 0E 00 5C                 LDR             D1, =0xC029B47C75430E78
.text:0000000000400A40 09 24 41 1F                 FMADD           D9, D0, D1, D9
.text:0000000000400A44 60 0E 00 5C                 LDR             D0, =0x402451A1CE8B2CB3
.text:0000000000400A48 08 25 40 1F                 FMADD           D8, D8, D0, D9
.text:0000000000400A4C 60 0E 00 5C                 LDR             D0, =0x4055400000000000
.text:0000000000400A50 08 29 60 1E                 FADD            D8, D8, D0
.text:0000000000400A54 00 01 79 1E                 FCVTZU          W0, D8
.text:0000000000400A58 C0 6A 33 38                 STRB            W0, [X22,X19]
.text:0000000000400A5C 73 06 00 91                 ADD             X19, X19, #1
.text:0000000000400A60 7F 16 00 F1                 CMP             X19, #5
.text:0000000000400A64 A1 F8 FF 54                 B.NE            loc_400978
.text:0000000000400A68 E0 03 16 AA                 MOV             X0, X22
.text:0000000000400A6C C5 8C 02 94                 BL              sub_4A3D80
.text:0000000000400A70 00 07 00 B4                 CBZ             X0, loc_400B50
.text:0000000000400A74 93 0B 00 F0                 ADRP            X19, #off_5736C0@PAGE
.text:0000000000400A78 E1 03 00 AA                 MOV             X1, X0
.text:0000000000400A7C 60 62 43 F9                 LDR             X0, [X19,#off_5736C0@PAGEOFF]
.text:0000000000400A80 E2 1B 00 94                 BL              sub_407A08
.text:0000000000400A84 BB FE FF 17                 B               loc_400570

This function was a tad bit weird to analyze because the string passed to the allocated buffer is generated in a cryptic way, so I decided to go with a dynamic approach and debug the application. First, I launched the pseudo application on a debug port as shown below.

Then I put a break point at the end of the loop, where the allocated buffer has been populated and read the string from the allocated buffer. I then set a new break point after the function call that takes the allocated buffer as a parameter and read the string returned by the function call.

This handler thus appears to obtain the username of the current user by querying the ‘USER’ environment variable, equivalent to the following C code.

char* tmp = malloc(5);

for (int i = 0; i < 5; i++)
    tmp[i] = expected(i); // fpu mumbu jumbo

char* username = getenv(tmp); // tmp = "USER"

if (username != 0)
    sub_407A08(off_5736C0, username); // too lazy to analyze - not important

Handler 0xd2 – Verify password

.text:00000000004006C0 B3 0B 00 90                 ADRP            X19, #off_5740C8@PAGE
.text:00000000004006C4 60 22 03 91                 ADD             X0, X19, #off_5740C8@PAGEOFF
.text:00000000004006C8 62 66 40 F9                 LDR             X2, [X19,#off_5740C8@PAGEOFF]
.text:00000000004006CC 01 04 40 F9                 LDR             X1, [X0,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:00000000004006D0 02 04 00 F9                 STR             X2, [X0,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:00000000004006D4 20 08 00 D1                 SUB             X0, X1, #2
.text:00000000004006D8 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:00000000004006DC 21 E0 5F 38                 LDURB           W1, [X1,#-2]
.text:00000000004006E0 3F 34 00 71                 CMP             W1, #0xD
.text:00000000004006E4 00 13 00 54                 B.EQ            loc_400944
.text:00000000004006E8 16 00 80 52                 MOV             W22, #0
.text:00000000004006EC 07 00 00 14                 B               loc_400708
.text:00000000004006F0             ; ---------------------------------------------------------------------------
.text:00000000004006F0
.text:00000000004006F0             loc_4006F0                              ; CODE XREF: sub_4004B0+470↓j
.text:00000000004006F0 20 04 00 D1                 SUB             X0, X1, #1
.text:00000000004006F4 D6 06 00 11                 ADD             W22, W22, #1
.text:00000000004006F8 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:00000000004006FC 21 F0 5F 38                 LDURB           W1, [X1,#-1]
.text:0000000000400700 3F 34 00 71                 CMP             W1, #0xD
.text:0000000000400704 00 12 00 54                 B.EQ            loc_400944
.text:0000000000400708
.text:0000000000400708             loc_400708                              ; CODE XREF: sub_4004B0+23C↑j
.text:0000000000400708                                                     ; sub_4004B0+490↓j
.text:0000000000400708 C8 02 62 1E                 SCVTF           D8, W22
.text:000000000040070C 01 90 66 1E                 FMOV            D1, #20.0
.text:0000000000400710 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400714 E3 45 02 94                 BL              loc_491EA0
.text:0000000000400718 12 40 60 1E                 FMOV            D18, D0
.text:000000000040071C 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400720 01 70 66 1E                 FMOV            D1, #19.0
.text:0000000000400724 B2 43 00 FD                 STR             D18, [X29,#0x1D00+var_1C80]
.text:0000000000400728 DE 45 02 94                 BL              loc_491EA0
.text:000000000040072C 13 40 60 1E                 FMOV            D19, D0
.text:0000000000400730 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400734 01 50 66 1E                 FMOV            D1, #18.0
.text:0000000000400738 B3 47 00 FD                 STR             D19, [X29,#0x1D00+var_1C78]
.text:000000000040073C D9 45 02 94                 BL              loc_491EA0
.text:0000000000400740 11 40 60 1E                 FMOV            D17, D0
.text:0000000000400744 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400748 01 30 66 1E                 FMOV            D1, #17.0
.text:000000000040074C B1 4B 00 FD                 STR             D17, [X29,#0x1D00+var_1C70]
.text:0000000000400750 D4 45 02 94                 BL              loc_491EA0
.text:0000000000400754 10 40 60 1E                 FMOV            D16, D0
.text:0000000000400758 00 41 60 1E                 FMOV            D0, D8
.text:000000000040075C 01 10 66 1E                 FMOV            D1, #16.0
.text:0000000000400760 B0 4F 00 FD                 STR             D16, [X29,#0x1D00+var_1C68]
.text:0000000000400764 CF 45 02 94                 BL              loc_491EA0
.text:0000000000400768 07 40 60 1E                 FMOV            D7, D0
.text:000000000040076C 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400770 01 D0 65 1E                 FMOV            D1, #15.0
.text:0000000000400774 A7 53 00 FD                 STR             D7, [X29,#0x1D00+var_1C60]
.text:0000000000400778 CA 45 02 94                 BL              loc_491EA0
.text:000000000040077C 06 40 60 1E                 FMOV            D6, D0
.text:0000000000400780 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400784 01 90 65 1E                 FMOV            D1, #14.0
.text:0000000000400788 A6 57 00 FD                 STR             D6, [X29,#0x1D00+var_1C58]
.text:000000000040078C C5 45 02 94                 BL              loc_491EA0
.text:0000000000400790 05 40 60 1E                 FMOV            D5, D0
.text:0000000000400794 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400798 01 50 65 1E                 FMOV            D1, #13.0
.text:000000000040079C A5 5B 00 FD                 STR             D5, [X29,#0x1D00+var_1C50]
.text:00000000004007A0 C0 45 02 94                 BL              loc_491EA0
.text:00000000004007A4 04 40 60 1E                 FMOV            D4, D0
.text:00000000004007A8 00 41 60 1E                 FMOV            D0, D8
.text:00000000004007AC 01 10 65 1E                 FMOV            D1, #12.0
.text:00000000004007B0 A4 5F 00 FD                 STR             D4, [X29,#0x1D00+var_1C48]
.text:00000000004007B4 BB 45 02 94                 BL              loc_491EA0
.text:00000000004007B8 03 40 60 1E                 FMOV            D3, D0
.text:00000000004007BC 00 41 60 1E                 FMOV            D0, D8
.text:00000000004007C0 01 D0 64 1E                 FMOV            D1, #11.0
.text:00000000004007C4 A3 63 00 FD                 STR             D3, [X29,#0x1D00+var_1C40]
.text:00000000004007C8 B6 45 02 94                 BL              loc_491EA0
.text:00000000004007CC 02 40 60 1E                 FMOV            D2, D0
.text:00000000004007D0 00 41 60 1E                 FMOV            D0, D8
.text:00000000004007D4 01 90 64 1E                 FMOV            D1, #10.0
.text:00000000004007D8 A2 67 00 FD                 STR             D2, [X29,#0x1D00+var_1C38]
.text:00000000004007DC B1 45 02 94                 BL              loc_491EA0
.text:00000000004007E0 0F 40 60 1E                 FMOV            D15, D0
.text:00000000004007E4 00 41 60 1E                 FMOV            D0, D8
.text:00000000004007E8 01 50 64 1E                 FMOV            D1, #9.0
.text:00000000004007EC AD 45 02 94                 BL              loc_491EA0
.text:00000000004007F0 0E 40 60 1E                 FMOV            D14, D0
.text:00000000004007F4 00 41 60 1E                 FMOV            D0, D8
.text:00000000004007F8 01 10 64 1E                 FMOV            D1, #8.0
.text:00000000004007FC A9 45 02 94                 BL              loc_491EA0
.text:0000000000400800 0D 40 60 1E                 FMOV            D13, D0
.text:0000000000400804 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400808 01 90 63 1E                 FMOV            D1, #7.0
.text:000000000040080C A5 45 02 94                 BL              loc_491EA0
.text:0000000000400810 0C 40 60 1E                 FMOV            D12, D0
.text:0000000000400814 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400818 01 10 63 1E                 FMOV            D1, #6.0
.text:000000000040081C A1 45 02 94                 BL              loc_491EA0
.text:0000000000400820 0B 40 60 1E                 FMOV            D11, D0
.text:0000000000400824 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400828 01 90 62 1E                 FMOV            D1, #5.0
.text:000000000040082C 9D 45 02 94                 BL              loc_491EA0
.text:0000000000400830 0A 40 60 1E                 FMOV            D10, D0
.text:0000000000400834 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400838 01 10 62 1E                 FMOV            D1, #4.0
.text:000000000040083C 99 45 02 94                 BL              loc_491EA0
.text:0000000000400840 09 40 60 1E                 FMOV            D9, D0
.text:0000000000400844 00 41 60 1E                 FMOV            D0, D8
.text:0000000000400848 01 10 61 1E                 FMOV            D1, #3.0
.text:000000000040084C 95 45 02 94                 BL              loc_491EA0
.text:0000000000400850 B2 4F 48 6D                 LDP             D18, D19, [X29,#0x1D00+var_1C80]
.text:0000000000400854 61 1E 00 5C                 LDR             D1, =0xBD8D59CBF1F29755
.text:0000000000400858 B1 43 49 6D                 LDP             D17, D16, [X29,#0x1D00+var_1C70]
.text:000000000040085C A7 1B 4A 6D                 LDP             D7, D6, [X29,#0x1D00+var_1C60]
.text:0000000000400860 73 0A 61 1E                 FMUL            D19, D19, D1
.text:0000000000400864 21 1E 00 5C                 LDR             D1, =0x3D28766E0DCDD4F5
.text:0000000000400868 A5 13 4B 6D                 LDP             D5, D4, [X29,#0x1D00+var_1C50]
.text:000000000040086C A3 0B 4C 6D                 LDP             D3, D2, [X29,#0x1D00+var_1C40]
.text:0000000000400870 52 4E 41 1F                 FMADD           D18, D18, D1, D19
.text:0000000000400874 E1 1D 00 5C                 LDR             D1, =0x3DD8459C23B87573
.text:0000000000400878 61 66 40 F9                 LDR             X1, [X19,#off_5740C8@PAGEOFF]
.text:000000000040087C 31 4A 41 1F                 FMADD           D17, D17, D1, D18
.text:0000000000400880 C1 1D 00 5C                 LDR             D1, =0xBE0160A7B0909AA3
.text:0000000000400884 22 00 40 39                 LDRB            W2, [X1]
.text:0000000000400888 10 46 41 1F                 FMADD           D16, D16, D1, D17
.text:000000000040088C A1 1D 00 5C                 LDR             D1, =0xBE516DA6A2FEE8C9
.text:0000000000400890 E7 40 41 1F                 FMADD           D7, D7, D1, D16
.text:0000000000400894 A1 1D 00 5C                 LDR             D1, =0x3E8683B0964CAEC2
.text:0000000000400898 C6 1C 41 1F                 FMADD           D6, D6, D1, D7
.text:000000000040089C A1 1D 00 5C                 LDR             D1, =0x3ECEE8DDEBF7CA3E
.text:00000000004008A0 A5 18 41 1F                 FMADD           D5, D5, D1, D6
.text:00000000004008A4 A1 1D 00 5C                 LDR             D1, =0xBF096B2F030D5757
.text:00000000004008A8 84 14 41 1F                 FMADD           D4, D4, D1, D5
.text:00000000004008AC A1 1D 00 5C                 LDR             D1, =0xBF4AA0EA1773F3B8
.text:00000000004008B0 63 10 41 1F                 FMADD           D3, D3, D1, D4
.text:00000000004008B4 A1 1D 00 5C                 LDR             D1, =0x3F90FB3E2768639B
.text:00000000004008B8 42 0C 41 1F                 FMADD           D2, D2, D1, D3
.text:00000000004008BC A1 1D 00 5C                 LDR             D1, =0x3FB4FFF455B24445
.text:00000000004008C0 EF 09 41 1F                 FMADD           D15, D15, D1, D2
.text:00000000004008C4 A1 1D 00 5C                 LDR             D1, =0xC015C17B6F3A3219
.text:00000000004008C8 CE 3D 41 1F                 FMADD           D14, D14, D1, D15
.text:00000000004008CC A1 1D 00 5C                 LDR             D1, =0x4053AB42ADF9F03E
.text:00000000004008D0 AD 39 41 1F                 FMADD           D13, D13, D1, D14
.text:00000000004008D4 A1 1D 00 5C                 LDR             D1, =0xC0841E44B9202542
.text:00000000004008D8 8C 35 41 1F                 FMADD           D12, D12, D1, D13
.text:00000000004008DC A1 1D 00 5C                 LDR             D1, =0x40AA971512D9A171
.text:00000000004008E0 6B 31 41 1F                 FMADD           D11, D11, D1, D12
.text:00000000004008E4 A1 1D 00 5C                 LDR             D1, =0xC0C76A66CE1099AB
.text:00000000004008E8 4A 2D 41 1F                 FMADD           D10, D10, D1, D11
.text:00000000004008EC A1 1D 00 5C                 LDR             D1, =0x40DB22200CEACA0E
.text:00000000004008F0 29 29 41 1F                 FMADD           D9, D9, D1, D10
.text:00000000004008F4 A1 1D 00 5C                 LDR             D1, =0xC0E3A70DE17C518A
.text:00000000004008F8 09 24 41 1F                 FMADD           D9, D0, D1, D9
.text:00000000004008FC 00 09 68 1E                 FMUL            D0, D8, D8
.text:0000000000400900 81 1D 00 5C                 LDR             D1, =0x40DFBBDDC432CA58
.text:0000000000400904 09 24 41 1F                 FMADD           D9, D0, D1, D9
.text:0000000000400908 80 1D 00 5C                 LDR             D0, =0xC0C549E91FCAA0A3
.text:000000000040090C 08 25 40 1F                 FMADD           D8, D8, D0, D9
.text:0000000000400910 80 1D 00 5C                 LDR             D0, =0x403B00000736D600
.text:0000000000400914 08 29 60 1E                 FADD            D8, D8, D0
.text:0000000000400918 00 01 65 1E                 FCVTAU          W0, D8
.text:000000000040091C 5F 00 20 6B                 CMP             W2, W0,UXTB
.text:0000000000400920 81 EE FF 54                 B.NE            loc_4006F0
.text:0000000000400924 A0 0B 00 90                 ADRP            X0, #byte_574010@PAGE
.text:0000000000400928 D6 06 00 11                 ADD             W22, W22, #1
.text:000000000040092C 02 40 00 39                 STRB            W2, [X0,#byte_574010@PAGEOFF]
.text:0000000000400930 20 04 00 D1                 SUB             X0, X1, #1
.text:0000000000400934 60 66 00 F9                 STR             X0, [X19,#off_5740C8@PAGEOFF]
.text:0000000000400938 21 F0 5F 38                 LDURB           W1, [X1,#-1]
.text:000000000040093C 3F 34 00 71                 CMP             W1, #0xD
.text:0000000000400940 41 EE FF 54                 B.NE            loc_400708
.text:0000000000400944
.text:0000000000400944             loc_400944                              ; CODE XREF: sub_4004B0+234↑j
.text:0000000000400944                                                     ; sub_4004B0+254↑j
.text:0000000000400944 61 22 03 91                 ADD             X1, X19, #off_5740C8@PAGEOFF
.text:0000000000400948 22 04 40 F9                 LDR             X2, [X1,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:000000000040094C 20 04 00 F9                 STR             X0, [X1,#(off_5740D0 - 0x5740C8)] ; byte_57D090
.text:0000000000400950 62 66 00 F9                 STR             X2, [X19,#off_5740C8@PAGEOFF]

This handler appears to verify the password buffer populated by the described handler, 0x80, by comparing its contents to values generated in a cryptic manner, equivalent to the following C code.

char* tmp = off_5740D0 - 2;

for (int i = 0; *tmp != '\r'; i++, tmp--)
{
    char c = expected(i); // fpu mumbu jumbo

    if (*tmp == b)
        byte_574010 = *tmp;
}

Handler 0x02 – Skip infinite loop

.text:0000000000400958 A0 0B 00 90                 ADRP            X0, #byte_574010@PAGE
.text:000000000040095C 00 40 40 39                 LDRB            W0, [X0,#byte_574010@PAGEOFF]
.text:0000000000400960 94 02 00 8B                 ADD             X20, X20, X0
.text:0000000000400964 03 FF FF 17                 B               loc_400570

This handler appears to increment the opcode buffer index variable by the last parsed valid password character from handler 0xd2. This effectively performs a virtual jump in the opcode buffer, equivalent to the following C code.

vjmp $+byte_574010;

Handlers 0xc0 and 0x7f – Loop delimiters

.text:0000000000400AF8             loc_400AF8                              ; CODE XREF: sub_4004B0+BC↑j
.text:0000000000400AF8 A0 0B 00 90                 ADRP            X0, #off_5740C8@PAGE
.text:0000000000400AFC 00 64 40 F9                 LDR             X0, [X0,#off_5740C8@PAGEOFF]
.text:0000000000400B00 00 00 40 39                 LDRB            W0, [X0]
.text:0000000000400B04 60 D3 FF 34                 CBZ             W0, loc_400570
.text:0000000000400B08 94 06 00 D1                 SUB             X20, X20, #1
.text:0000000000400B0C 20 00 80 D2                 MOV             X0, #1
.text:0000000000400B10 A1 6A 74 38                 LDRB            W1, [X21,X20]
.text:0000000000400B14 3F 00 03 71                 CMP             W1, #0xC0
.text:0000000000400B18 00 01 00 54                 B.EQ            loc_400B38
.text:0000000000400B1C
.text:0000000000400B1C             loc_400B1C                              ; CODE XREF: sub_4004B0+684↓j
.text:0000000000400B1C 3F FC 01 71                 CMP             W1, #0x7F
.text:0000000000400B20 00 14 80 9A                 CINC            X0, X0, EQ
.text:0000000000400B24 60 D2 FF B4                 CBZ             X0, loc_400570
.text:0000000000400B28
.text:0000000000400B28             loc_400B28                              ; CODE XREF: sub_4004B0+68C↓j
.text:0000000000400B28 94 06 00 D1                 SUB             X20, X20, #1
.text:0000000000400B2C A1 6A 74 38                 LDRB            W1, [X21,X20]
.text:0000000000400B30 3F 00 03 71                 CMP             W1, #0xC0
.text:0000000000400B34 41 FF FF 54                 B.NE            loc_400B1C
.text:0000000000400B38
.text:0000000000400B38             loc_400B38                              ; CODE XREF: sub_4004B0+668↑j
.text:0000000000400B38 00 04 00 D1                 SUB             X0, X0, #1
.text:0000000000400B3C 60 FF FF B5                 CBNZ            X0, loc_400B28
.text:0000000000400B40 8C FE FF 17                 B               loc_400570

The 0xc0 and 0x7f handler appears to be loop delimiter handlers. Upon reaching a 0x7f handler, the instruction pointer data is compared to zero. If the data is non-zero, the opcode buffer index variable is decremented, i.e. the opcode buffer moves backwards, until reaching a 0xc0 handler. This effectively means that the 0xc0 initiates a loop condition, and the 0x7f handler terminates the loop condition and jumps back in the event of a fulfilled non-zero condition.


The trained eye might notice that many of these handlers exhibit behavior extremely similar to that of the esoteric programming language Brainfuck.

Now that we know what each of the individual handlers do, we can go ahead and recover the expected password. Ultimately, we want to put a break point at the address in handler 0xd2 where the password buffer is compared to the expected password as shown in the illustration below.

We start by launching the pseudo binary on debug port 8000.

We can now connect a gdb instance to debug port 8000, put a break point at the desired address and continue execution of the binary.

We can now enter a password of arbitrary length. The password should be long enough to iterate enough expected characters to dump the entire expected string. We chose to repeat the numbers 0-9 two times in a row as shown in the illustration below.

Our breakpoint should now be hit as shown in the illustration below. We can now dump the contents of the W0 register, in which the expected byte resides.

We continue this cycle until we reach the end of the string.

As seen in the illustration above, we have reached the terminating null-byte for the string, and are starting to see garbage data being printed afterwards. Upon having collected all the expected bytes, we should have obtained a list of bytes as shown below.

0x1b, 0x03, 0x19, 0x01, 0x07, 0x0a, 0x16, 0x01, 0x0e, 0x0e, 0x03, 0x01, 0x15, 0x0f, 0x18, 0x20

As seen in handler 0x80, in which the input was read into the password buffer, all inputs are decremented by 0x5e before being compared to the above byte sequence. We should therefore be able to reconstruct the expected input by adding 0x5e to the byte sequence shown above. Furthermore, the bytes were verified against the expected bytes in reverse order in handler 0xd2, and the decoded password should thus be reversed before being printed. This can be scripted in Python as shown below.

encoded = [0x1b, 0x03, 0x19, 0x01, 0x07, 0x0a, 0x16, 0x01, 0x0e, 0x0e, 0x03, 0x01, 0x15, 0x0f, 0x18, 0x20]
decoded = ''.join(reversed([chr(c + 0x5e) for c in encoded]))

print decoded

We can now run our script to decode the password.

We can now enter the password into the binary and obtain the flag.

And there you have it – the challenge has been solved!

Leave a Reply