Radare2: Internal grep breaks r2pipe output

Created on 2 Apr 2016  Â·  15Comments  Â·  Source: radareorg/radare2

I wrote a script using r2pipe binding, but there is not outpout executing the last line
the input file is here
Input file

import r2pipe

r2=r2pipe.open("stage3.bin")
r2.cmd("aa")
r2.cmd("s main")
nextaddr=r2.cmd("pd 50~mov esi:0[4]")
print nextaddr

print "s " + nextaddr

r2.cmd("s " + nextaddr)
print r2.cmd("? $$")

print r2.cmd("pd")  # no output this line
consoleui r2pipe remote scripting

Most helpful comment

@jpenalbae what do you think about this? can you confirm the issue is happening with the nodejs api too?

As long as all bindings must be affected, this makes me think that we should move r2pipe into a separate repo (after release) and add a testsuite for it and a good script database with documentation so people can learn how to use r2pipe quickier.

All 15 comments

And if I execute the command in ipython, I got even more weird results:

In [1]: import r2pipe
In [2]: r2=r2pipe.open("stage3.bin")
In [3]: r2.cmd("aa")
  [x] Analyze all flags starting with sym. and entry0 (aa) 
Out[3]: u''

In [4]: r2.cmd("s main")
Out[4]: u''

In [5]: nextaddr=r2.cmd("pd 50~mov esi:0[4]")

In [6]: print nextaddr
0x4007fd

In [7]: print "s " + nextaddr
s 0x4007fd

In [8]: r2.cmd("s " + nextaddr)
Out[8]: u''

In [9]: print r2.cmd("? $$")  # no output 

In [10]: print r2.cmd("? $$") # correct output 
4196349 0x4007fd 020003775 4M 40000:07fd 4196349 11111101 4196349.0 0.000000f 0.000000


In [11]: print r2.cmd("pd")   #wrong output
4196349 0x4007fd 020003775 4M 40000:07fd 4196349 11111101 4196349.0 0.000000f 0.000000

In [12]: print r2.cmd("pd")
; DATA XREF from 0x0040114b (unk)
        0x004007fd      55             push rbp
        0x004007fe      4889e5         mov rbp, rsp
        0x00400801      4883ec20       sub rsp, 0x20
        0x00400805      897dec         mov dword [rbp - 0x14], edi
        0x00400808      0fb605b13820.  movzx eax, byte [rip + 0x2038b1] ; [0x6040c0:1]=56 ; "8.2-19ubuntu1) 4.8.2" @ 0x6040c0
        0x0040080f      0fbec0         movsx eax, al
        0x00400812      8945fc         mov dword [rbp - 4], eax
        0x00400815      8b45fc         mov eax, dword [rbp - 4]
        0x00400818      69c8e8030000   imul ecx, eax, 0x3e8
        0x0040081e      ba79787878     mov edx, 0x78787879
        0x00400823      89c8           mov eax, ecx
        0x00400825      f7ea           imul edx
        0x00400827      c1fa05         sar edx, 5
        0x0040082a      89c8           mov eax, ecx
        0x0040082c      c1f81f         sar eax, 0x1f
        0x0040082f      29c2           sub edx, eax
        0x00400831      89d0           mov eax, edx
        0x00400833      8945fc         mov dword [rbp - 4], eax

this line looks problematic to me: nextaddr=r2.cmd("pd 50~mov esi:0[4]")

using pd and column grep is a bad idea, better use pi like this: pi 50~mov esi:0[4]

This is the fixed script (i think): Note the :0[4] -> [4]:0 change too

import r2pipe

r2=r2pipe.open("stage3.bin")
r2.cmd("aa")
r2.cmd("s main")

while True:
        nextaddr=r2.cmd("pi 50~mov esi[2]:0")
        if not nextaddr:
                break
        print nextaddr
        print "s " + nextaddr
        r2.cmd("s " + nextaddr)
        print r2.cmd("? $$")
        print "end"

@radare Thanks for pointing out the problems in my script.
Yes, there are some problems in my script. but what I wanted to report to you guys is that there are some serious bugs concerning the output of r2.cmd API in r2pipe.

The evidence is as follows:

Here is my code:

import r2pipe

r2=r2pipe.open("stage3.bin")
r2.cmd("aa")
r2.cmd("s main")

while True:
    nextaddr=r2.cmd("pi 50~mov esi:0[2]") #I want to get the second column of the first row here
    if not nextaddr:
        break
    print "1. "+ nextaddr
    print "2. s " + nextaddr
    r2.cmd("s " + nextaddr)
    print "3. " + r2.cmd("? $$")
    print "4. end"

And the output is as follows

[x] Analyze all flags starting with sym. and entry0 (aa)
1. 0x4007fd    # the first iteration

2. s 0x4007fd

3.       # the output of ? $$ is empty
4. end
# the second iteration
# this output must be the output of the previous command(? $$)
1. 4196349 0x4007fd 020003775 4M 40000:07fd 4196349 11111101 4196349.0 0.000000f 0.000000

2. s 4196349 0x4007fd 020003775 4M 40000:07fd 4196349 11111101 4196349.0 0.000000f 0.000000

3. 
4. end

Obviously, there must be some synchronization issues.
In step 3 of the first iteration, we issued a command ? $$ to r2, but we got nothing returned.
Then in first step of the next iteration, we got the results of the results of step 3 in the previous iteration.

the root of the problem is in the line grep using a different order of options. which is not really related to r2pipe, but causes some bad output that is wrongly interepreted by r2pipe.

will look into it when i have time (if i do) :P otherwise if anyone have some time to check this out it will be great

On 03 Apr 2016, at 04:16, Hui Peng [email protected] wrote:

@radare https://github.com/radare Thanks for pointing out the problems in my script.
Yes, there are some problems in my script. but what I want to report to you guys is that there is some serious bugs concerning the output of r2.cmd API in r2pipe.

The evidence is as follows:
`import r2pipe

r2=r2pipe.open("stage3.bin")
r2.cmd("aa")
r2.cmd("s main")

while True:
nextaddr=r2.cmd("pi 50~mov esi:0[2]")
if not nextaddr:
break
print "1. "+ nextaddr
print "2. s " + nextaddr
r2.cmd("s " + nextaddr)
print "3. " + r2.cmd("? $$")
print "4. end"
`

—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub https://github.com/radare/radare2/issues/4489#issuecomment-204852560

file is 404

I think the problem here is that the command you are passing to cmd() contains newlines. i have reproduced a tiny test case with just this and it fails because of the newline. We can solve this in different ways:

  • Avoid newlines in the commands passed to cmd() in the r2pipe.py api
  • Strip() and Change newlines by ; to handle newlines properly
  • Fix multiple commands with newlines in r2pipe at core level

Simple test case for this:

r2=r2pipe.open("/bin/ls")
txt = r2.cmd("?e hello\n?e world")
print txt

your script works fine if you .strip() the offset

also, maybe we should trim() all outputs

@jpenalbae what do you think about this? can you confirm the issue is happening with the nodejs api too?

As long as all bindings must be affected, this makes me think that we should move r2pipe into a separate repo (after release) and add a testsuite for it and a good script database with documentation so people can learn how to use r2pipe quickier.

Same happens in node.

I would suggest throwing an exception noting that the command contains an invalid character, and point to the bad char.

Imho we should trim and then check if the cmd contains a newline.. Or maybe any non printable char to throw an exception

On 20 May 2016, at 17:18, Jaime Peñalba [email protected] wrote:

Same happens in node.

I would suggest throwing an exception noting that the command contains an invalid character, and point to the bad char.

—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

can you try with latest 0.8.2 (pip upgrade)? i think we need to do more changes on this, because i think we should ban any non-printable char in this interface. i have also noticed a problem with ;

moving for 0.10.4 because the main / silly issue is now fixed, but requires deeper fixing. python and node bindings have been updated

i think we can close this issue now :)

Was this page helpful?
0 / 5 - 0 ratings