ropes 128pts

Description:
It's not just a string, it's a rope!

File:
ropes

Author: 
NotDeGhost

on this challenge we were given Mach-O binary file ropes.

❯ file ropes 
ropes: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>

to solve the first challenge is not too difficult, we can use the strings command to find interesting strings that we might be able to see the flag.

❯ strings ropes
...
/usr/lib/libSystem.B.dylib
Give me a magic number: 
First part is: flag{r0pes_ar3_
Second part is: just_l0ng_str1ngs}
@dyld_stub_binder
@_printf
...

FLAG : flag{r0pes_ar3_just_l0ng_str1ngs}


bubbly 395pts

Description:
It never ends

nc 2020.redpwnc.tf 31039

File:
bubbly

Author: 
dns

At the challenge we are given binary files bubbly

❯ file bubbly 
bubbly: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=edb56d2d9355bcee01909f171d8a272a3e82d053, with debug_info, not stripped

The following is a pseudocode snippet from the bubbly program, as we see there are variable array nums and there are repeats, which are intended to move each element position to array nums and there is a check() function, this function is useful for checking each element on Array nums whether the element in the array nums is sorted, if the element array nums is already passed the check () function returns the value 0 == True if it does not return the value 1 == False.

...
.data:0000000000004060 nums            dd 1, 10, 3, 2, 5, 9, 8, 7, 4, 6
...
  puts("I hate my data structures class! Why can't I just sort by hand?");
  for ( pass = 0; ; pass = check() )
  {
    unused = __isoc99_scanf("%d", &i);
    if ( i > 8 )
      break;
    nums[i] ^= nums[i + 1];
    nums[i + 1] ^= nums[i];
    nums[i] ^= nums[i + 1];
  }
 ...
BOOL8 __fastcall check()
{
  uint32_t i; // [rsp+0h] [rbp-8h]
  bool pass; // [rsp+7h] [rbp-1h]

  pass = 1;
  for ( i = 0; i <= 8; ++i )
  {
    if ( nums[i] > nums[i + 1] )
      return 0;
  }
  return pass;
}

To solve this challenge I use hackerearth to make it easier to solve the challenge. After getting a value to sort the array of nums, enter a value greater than 8 to exit the loop.

❯ ./connect.sh        
I hate my data structures class! Why can't I just sort by hand?
1
2
3
4
5
6
7
8
1
4
5
6
7
4
5
6
4
5
3
9
Well done!
flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}

FLAG : flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}


SMarT-solver 475pts

Description:
Find the correct flag. :)

NOTE: All letters in the flag are lowercase

File:
SMarT-solver

Author: 
MrSlick

In the following challenges we are given a binary file SMarT-solver.

❯ file SMarT-solver
SMarT-solver: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=27bf1ae8e39bad973a605ab44e3b36a64e2134c6, not stripped

If you are familiar with the challenge of reversing, maybe we will get to know what we should do next. If you don’t understand, let me explain briefly. If we pay attention i think they wants to try saying “SMT-solver”, so we need to prepare our z3 already installed to help us solve this challenge and we are also told that All letters in the flag are lowercase. Let’s look deeper to understand how the binary works.

...
     90d:       48 8d 85 e0 fe ff ff    lea    rax,[rbp-0x120]	<-----------+
     914:       48 89 c7                mov    rdi,rax                      |
     917:       e8 c4 fd ff ff          call   6e0 <strlen@plt>             |
     91c:       48 83 f8 48             cmp    rax,0x48     <---------------+---> compare input length with 0x48 / 72
     920:       0f 86 9c b0 01 00       jbe    1b9c2 <main+0x1b168>         
     926:       0f b6 95 e0 fe ff ff    movzx  edx,BYTE PTR [rbp-0x120] <---+
     92d:       0f b6 85 e1 fe ff ff    movzx  eax,BYTE PTR [rbp-0x11f] <---| 
     934:       38 c2                   cmp    dl,al        <---------------|
     936:       0f 83 8c b0 01 00       jae    1b9c8 <main+0x1b16e>         |
     93c:       0f b6 95 e0 fe ff ff    movzx  edx,BYTE PTR [rbp-0x120] <---|
     943:       0f b6 85 e2 fe ff ff    movzx  eax,BYTE PTR [rbp-0x11e] <---|
     94a:       38 c2                   cmp    dl,al        <---------------+---> compare each character in our input
     94c:       0f 86 7c b0 01 00       jbe    1b9ce <main+0x1b174>         |
     952:       0f b6 95 e0 fe ff ff    movzx  edx,BYTE PTR [rbp-0x120] <---|
     959:       0f b6 85 e3 fe ff ff    movzx  eax,BYTE PTR [rbp-0x11d] <---|
     960:       38 c2                   cmp    dl,al        <---------------|
     962:       0f 83 6c b0 01 00       jae    1b9d4 <main+0x1b17a>         |
...

After a few minutes doing static analysis it can be concluded that the flag length is 72 characters and that each character is compared to each other. The next step is to take the assembly code and clean it to make the code look clearer. After that, let’s create a script to complete this challenge. Visit my github to see my solver code

❯ python solver.py
flag{thequickbrownfoxjumpedoverthelazydogandlearnedhowtoautomateanalysis}

❯ python solver.py | ./SMarT-solver
Welcome to SMarT solver!
The #1 solution for your flag checking needs.

Enter a flag: 
Correct input!

FLAG : flag{thequickbrownfoxjumpedoverthelazydogandlearnedhowtoautomateanalysis}


a-round-mechanism 495pts

Description:
I found a respectable mainframe, can you help me get in? Flag is in flag.txt

nc 2020.redpwnc.tf 31359

File:
ARM

Author:
green beans

In this challenge we are given a 32-bit ARM stripped binary file

❯ file ARM
ARM: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=714b6b1a1949f1f0d3912e7e13fef4420e2d4efa, stripped

After spending several hours doing static analysis I found a way to solve this challenge. As you can see here is a program flow where the length of the input must be 0x16 / 22 characters, the next step is that each character will be xor with 0x12 / 18.

...
.data:00086064                 LDR     R2, =loc_86008 <-------- Our input is stored at loc_86008
.data:00086068                 MOV     R0, #0     <---------+
.data:0008606C                 MOV     R1, #0x16  <---------+-- Prepare looping 22 times
.data:00086070 loc_86070                               ; CODE XREF: .data:00086090↓j
.data:00086070                 LDRB    R3, [R2,R0] <-----------+
.data:00086074                 MOV     R4, R3                  |
.data:00086078                 EOR     R4, R4, #0x12 <---------+-- Each character will be xor with 18
.data:0008607C                 STRB    R4, [R2,R0]
.data:00086080                 CMP     R3, #0xA
.data:00086084                 BLEQ    loc_163BC
.data:00086088                 ADD     R0, R0, #1
.data:0008608C                 CMP     R0, R1   <--------+
.data:00086090                 BLE     loc_86070  <------+-- Return to loc_86070 if R0 is still smaller than R1 
...

Then the sub_860EC function will be called and the value 1 and our input as parameters. The essence of the sub_860EC function every two characters from our input will be shifted left and shifted right once. After that the two results will be added up then the result is shifted right 7 times and subtracted by 1. This will be repeated 22 times.

...
.data:00086094                 LDR     R0, =loc_86008 <-----+
.data:00086098                 MOV     R1, #1               |
.data:0008609C                 BL      sub_860EC <----------+-- sub_860EC(R0, R1)
...
.data:000860EC sub_860EC                               ; CODE XREF: .data:0008609C↑p
.data:000860EC                                         ; sub_860EC+70↓p
.data:000860EC                 PUSH    {LR}
.data:000860F0                 PUSH    {R12}
.data:000860F4                 PUSH    {R0}
.data:000860F8                 PUSH    {R1}
.data:000860FC                 SUB     SP, SP, #8
.data:00086100                 MOV     R12, SP
.data:00086104                 ADDLT   R1, R1, #1
.data:00086108                 CMP     R1, #0x16 <-----+
.data:0008610C                 BNE     loc_86118 <-----+-- Jump to loc_86118 if R1 not Equal 0x16 / 22
.data:00086110                 MOV     R0, #1
.data:00086114                 B       loc_86160 <----- exit from function sub_860EC
.data:00086118 ; ---------------------------------------------------------------------------
.data:00086118
.data:00086118 loc_86118                               ; CODE XREF: sub_860EC+20↑j
.data:00086118                 MOV     R6, R0  <--------------- Our input is moved to R6 from R0 in parameter 1
.data:0008611C                 MOV     R8, R1  <----------+ 
.data:00086120                 LDRB    R9, [R6,R8] <------+ R9 = R6[R8] Take the next character from our input
.data:00086124                 MOV     R10, R9
.data:00086128                 SUB     R5, R8, #1 <--------+ R8 is subtracted 1 to retrieve the previous character
.data:0008612C                 LDRB    R12, [R6,R5] <------+ R12 = R6[R5]
.data:00086130                 MOV     R5, R12
.data:00086134                 MOV     R5, R5,LSR#1  <------+ LSR (Logical Shift Right) R5 = (R5 >> 1)
.data:00086138                 MOV     R10, R10,LSL#1 <-----+ LSL (Logical Shift Left) R10 = (R10 << 1)
.data:0008613C                 ADD     R7, R5, R10 <--------+ R7 = (R5 + R10)
.data:00086140                 MOV     R10, R7
.data:00086144                 MOV     R7, R7,LSR#7  <------+ R7 = (R7 >> 7)
.data:00086148                 MOV     R10, R10,LSR R7      |
.data:0008614C                 SUB     R10, R10, #1 <-------+ R10 = (R7 >> (R10 >> R7)) - 1 
.data:00086150                 STRB    R10, [R6,R8] <----------- R6[R8] = R10
.data:00086154                 LDR     R0, =loc_86008 <-----+
.data:00086158                 MOV     R1, R8               |
.data:0008615C                 BL      sub_860EC <----------+-- sub_860EC(R0, R1)
.data:00086160
.data:00086160 loc_86160                               ; CODE XREF: sub_860EC+28↑j
.data:00086160                 ADD     SP, SP, #8
.data:00086164                 POP     {R1}
.data:00086168                 POP     {R0}
.data:0008616C                 POP     {R12}
.data:00086170                 POP     {PC}
...

Last but not least the results of our input will be compared with te@B}efFk~{^Ixv@}y\\BC4 Because this program is ‘little enddian’ it should look like this 4CB\\y}@vxI^{~kFfe}B@et.

...
.data:000860A0                 LDR     R2, =loc_86008
.data:000860A4                 LDR     R3, =aTeBEffkIxvYBc4 ; "te@B}efFk~{^Ixv@}y\\BC4"
...

The following is the output of my solver. Visit my github to see my solver code.

❯ python3 solver.py
Know 1st char : 4
Restore 2nd char: C
- possibility : 7
- possibility : {
- possibility : |
-----------------------------------
Result - 7 : 473Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &%!_q3quNd_ws_fD_wu#DN
-----------------------------------
Result - { : 4{3Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &i!_q3quNd_ws_fD_wu#DN
-----------------------------------
Result - | : 4|3Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &n!_q3quNd_ws_fD_wu#DN

I tried all three keys which I found all worked well.

❯ ./connect.sh
I hear you've come to bargain for flags
 I'm a reasonable machine, if you guess the password I can give you a flag
&%!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag:   cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}

❯ ./connect.sh
I hear you've come to bargain for flags
 I'm a reasonable machine, if you guess the password I can give you a flag
&i!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag:   cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}

❯ ./connect.sh
I hear you've come to bargain for flags
 I'm a reasonable machine, if you guess the password I can give you a flag
&n!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag:   cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}

FLAG : flag{4_r3gu14R_m0N5tr051Ty}