1

I am trying to solve a CTF challenge but I am very much out of my depth and nothing online is helping me very much. This is what I'm working with currently

|           0x55b3fd508a41      4889e5         mov rbp, rsp                                                                                                   
|           0x55b3fd508a44      4881ec900100.  sub rsp, 0x190                                                                                                 
|           0x55b3fd508a4b      89bd7cfeffff   mov dword [local_184h], edi       ; argc                                                                       
|           0x55b3fd508a51      4889b570feff.  mov qword [local_190h], rsi       ; argv                                                                       
|           0x55b3fd508a58      64488b042528.  mov rax, qword fs:[0x28]       ; [0x28:8]=-1 ; '(' ; 40                                                        
|           0x55b3fd508a61      488945f8       mov qword [local_8h], rax                                                                                      
|           0x55b3fd508a65      31c0           xor eax, eax                                                                                                   
|           0x55b3fd508a67      c78588feffff.  mov dword [local_178h], 0x2d       ; '-' ; 45                                                                  
|           0x55b3fd508a71      c7858cfeffff.  mov dword [local_174h], 0x32       ; '2' ; 50                                                                  
|           0x55b3fd508a7b      83bd7cfeffff.  cmp dword [local_184h], 1       ; rdi ; [0x1:4]=-1                                                             
|       ,=< 0x55b3fd508a82      0f8e77010000   jle 0x55b3fd508bff      ;[1]                                                                                   
|       |   0x55b3fd508a88      488b8570feff.  mov rax, qword [local_190h]                                                                                    
|       |   0x55b3fd508a8f      4883c008       add rax, 8                                                                                                     
|       |   0x55b3fd508a93      488b00         mov rax, qword [rax]                                                                                           
|       |   0x55b3fd508a96      488d35fb0200.  lea rsi, str.calc       ; 0x55b3fd508d98 ; "calc"                                                              
|       |   0x55b3fd508a9d      4889c7         mov rdi, rax   

I am interested in the line 0x55b3fd508a7b, what does local_184h mean? How do I edit this value in order to change the result of the upcoming jle? Or, how do I change the result of the jle command without having to change local_184h? I read that it checks the sign flag so I edited the rflags register to be 0x0080 less than it was, hoping that would change the outcome of the jle but it didn't.

2
  • Are you using the radare2 debugger or gdb?
    – sudhackar
    Commented Nov 17, 2020 at 11:27
  • @sudhackar Radare2 debugger
    – retsek680
    Commented Nov 17, 2020 at 11:34

1 Answer 1

2

According to Intel's manual

3.4.3.1
Status Flags
The status flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the ADD, SUB, MUL, and DIV instructions. The status flag functions are:
CF (bit 0) Carry flag — Set if an arithmetic operation generates a carry or a borrow out of the most- significant bit of the result; cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in multiple-precision arithmetic.
PF (bit 2) Parity flag — Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise.
AF (bit 4) Auxiliary Carry flag — Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This flag is used in binary-coded decimal (BCD) arithmetic.
ZF (bit 6) Zero flag — Set if the result is zero; cleared otherwise.
SF (bit 7) Sign flag — Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a positive value and 1 indicates a negative value.)
OF (bit 11) Overflow flag — Set if the integer result is too large a positive number or too small a negativenumber (excluding the sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for signed-integer (two’s complement) arithmetic.

So to set individual flags you need to operate on the individual bits

to clear nth bit in a number

number &= ~(1 << n)

For SF n = 7, so to unset SF

eflags &= ~(1 << 7)

with this simple code

int main(int argc, char **argv) {
    int in;
    scanf("%d", &in);
    if (in > 10) {
        puts("greater");
    } else {
        puts("less");
    }
    return 0;
}

This can be achieved easily

[re] r2 -d test
Process with PID 17193 started...
= attach 17193 17193
bin.baddr 0x55c79226b000
Using 0x55c79226b000
asm.bits 64
[0x7fb03234b090]> dcu sym.main
Continue until 0x55c79226b83a using 1 bpsize
hit breakpoint at: 0x55c79226b83a
[0x55c79226b83a]> pd20
            ;-- main:
            ;-- rax:
            ;-- rip:
            0x55c79226b83a      55             push rbp
            0x55c79226b83b      4889e5         mov rbp, rsp
            0x55c79226b83e      4883ec20       sub rsp, 0x20
            0x55c79226b842      897dec         mov dword [rbp - 0x14], edi
            0x55c79226b845      488975e0       mov qword [rbp - 0x20], rsi
            0x55c79226b849      64488b042528.  mov rax, qword fs:[0x28]
            0x55c79226b852      488945f8       mov qword [rbp - 8], rax
            0x55c79226b856      31c0           xor eax, eax
            0x55c79226b858      488d45f4       lea rax, [rbp - 0xc]
            0x55c79226b85c      4889c6         mov rsi, rax
            0x55c79226b85f      488d3dee0100.  lea rdi, [0x55c79226ba54] ; "%d"
            0x55c79226b866      b800000000     mov eax, 0
            0x55c79226b86b      e880feffff     call sym.imp.scanf
            0x55c79226b870      8b45f4         mov eax, dword [rbp - 0xc]
            0x55c79226b873      83f80a         cmp eax, 0xa            ; 10
        ┌─< 0x55c79226b876      7e0e           jle 0x55c79226b886
        │   0x55c79226b878      488d3dd80100.  lea rdi, str.greater    ; 0x55c79226ba57 ; "greater"
        │   0x55c79226b87f      e88cfeffff     call sym.imp.puts
       ┌──< 0x55c79226b884      eb0c           jmp 0x55c79226b892
       │└─> 0x55c79226b886      488d3dd20100.  lea rdi, str.less       ; 0x55c79226ba5f ; "less"
[0x55c79226b83a]> dcu 0x55c79226b876
Continue until 0x55c79226b876 using 1 bpsize
7
hit breakpoint at: 0x55c79226b876
[0x55c79226b876]> dr eflags
0x00000293
[0x55c79226b876]> dr eflags=0x213
0x00000293 ->0x00000213
[0x55c79226b876]> dc
greater
(17193) Process exited with status=0x0

Here eflags was updated from 0x00000293 to 0x00000213 since

0x293&~(1<<7) = 0x213 

The input was 7 but the output was "Greater" since dr eflags=0x213 unset SF

Similarly in the other direction, to set SF

eflags |= (1 << 7)

For larger input it can be used to go to the smaller branch

[re] r2 -d test
Process with PID 23724 started...
= attach 23724 23724
bin.baddr 0x562ccba44000
Using 0x562ccba44000
asm.bits 64
[0x7f568eeaa090]> dcu sym.main
Continue until 0x562ccba4483a using 1 bpsize
hit breakpoint at: 0x562ccba4483a
[0x562ccba4483a]> pd20
            ;-- main:
            ;-- rax:
            ;-- rip:
            0x562ccba4483a      55             push rbp
            0x562ccba4483b      4889e5         mov rbp, rsp
            0x562ccba4483e      4883ec20       sub rsp, 0x20
            0x562ccba44842      897dec         mov dword [rbp - 0x14], edi
            0x562ccba44845      488975e0       mov qword [rbp - 0x20], rsi
            0x562ccba44849      64488b042528.  mov rax, qword fs:[0x28]
            0x562ccba44852      488945f8       mov qword [rbp - 8], rax
            0x562ccba44856      31c0           xor eax, eax
            0x562ccba44858      488d45f4       lea rax, [rbp - 0xc]
            0x562ccba4485c      4889c6         mov rsi, rax
            0x562ccba4485f      488d3dee0100.  lea rdi, [0x562ccba44a54] ; "%d"
            0x562ccba44866      b800000000     mov eax, 0
            0x562ccba4486b      e880feffff     call sym.imp.scanf
            0x562ccba44870      8b45f4         mov eax, dword [rbp - 0xc]
            0x562ccba44873      83f80a         cmp eax, 0xa            ; 10
        ┌─< 0x562ccba44876      7e0e           jle 0x562ccba44886
        │   0x562ccba44878      488d3dd80100.  lea rdi, str.greater    ; 0x562ccba44a57 ; "greater"
        │   0x562ccba4487f      e88cfeffff     call sym.imp.puts
       ┌──< 0x562ccba44884      eb0c           jmp 0x562ccba44892
       │└─> 0x562ccba44886      488d3dd20100.  lea rdi, str.less       ; 0x562ccba44a5f ; "less"
[0x562ccba4483a]> dcu 0x562ccba44876
Continue until 0x562ccba44876 using 1 bpsize
100
hit breakpoint at: 0x562ccba44876
[0x562ccba44876]> dr eflags
0x00000216
[0x562ccba44876]> "?vx eflags|(1 << 7)"
0x00000296
[0x562ccba44876]> dr eflags=0x296
0x00000216 ->0x00000296
[0x562ccba44876]> dc
less
(23724) Process exited with status=0x0

Additionally looking at your disassembly's annotations it seems like you are analyzing the main function of the binary. Here we copy argc from edi to local_184h

|           0x55b3fd508a4b      89bd7cfeffff   mov dword [local_184h], edi       ; argc

So if you start you binary with at least 1 argument it should work. Something like

$ r2 -d binary arg1 

should work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.