JonathanSalwan / Triton

Triton is a dynamic binary analysis library. Build your own program analysis tools, automate your reverse engineering, perform software verification or just emulate code.
https://triton-library.github.io
Apache License 2.0
3.4k stars 525 forks source link

Fulldump problem #1143

Closed 0xFF1E071F closed 2 years ago

0xFF1E071F commented 2 years ago

Hello Jonathan; I am trying to walk-through baby-re for learning Triton. But i am stuck while creating a fulldump.

I am using ArchLinux + XFCE gdb: 12.1 python: 3.10.5 peda: 1.2 peda patch from you

This is the output of gdb with baby-re

$ gdb ./baby-re   
GNU gdb (GDB) 12.1

<... snip ...>

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./baby-re...
(No debugging symbols found in ./baby-re)
gdb-peda$ b CheckSolution
Breakpoint 1 at 0x4006ca
gdb-peda$ c
The program is not being run.
gdb-peda$ r
Starting program: /home/username/Downloads/baby-re 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Var[0]: asdasdasd
Var[1]: Var[2]: Var[3]: Var[4]: Var[5]: Var[6]: Var[7]: Var[8]: Var[9]: Var[10]: Var[11]: Var[12]: Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

[----------------------------------registers-----------------------------------]
RAX: 0x7fffffffe120 --> 0x0 
RBX: 0x7fffffffe298 --> 0x7fffffffe530 ("/home/username/Downloads/baby-re")
RCX: 0x7fffffffdbe0 --> 0x7fffffffdc54 --> 0x0 
RDX: 0x0 
RSI: 0x61 ('a')
RDI: 0x7fffffffe120 --> 0x0 
RBP: 0x7fffffffe110 --> 0x7fffffffe180 --> 0x1 
RSP: 0x7fffffffe110 --> 0x7fffffffe180 --> 0x1 
RIP: 0x4006ca (<CheckSolution+4>:   sub    rsp,0x2c0)
R8 : 0xa ('\n')
R9 : 0x61 ('a')
R10: 0xffffffff 
R11: 0x0 
R12: 0x0 
R13: 0x7fffffffe2a8 --> 0x7fffffffe557 ("DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus")
R14: 0x0 
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2a0 --> 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4006c1 <frame_dummy+33>:   jmp    0x400640 <register_tm_clones>
   0x4006c6 <CheckSolution>:    push   rbp
   0x4006c7 <CheckSolution+1>:  mov    rbp,rsp
=> 0x4006ca <CheckSolution+4>:  sub    rsp,0x2c0
   0x4006d1 <CheckSolution+11>: mov    QWORD PTR [rbp-0x2b8],rdi
   0x4006d8 <CheckSolution+18>: mov    rax,QWORD PTR fs:0x28
   0x4006e1 <CheckSolution+27>: mov    QWORD PTR [rbp-0x8],rax
   0x4006e5 <CheckSolution+31>: xor    eax,eax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe110 --> 0x7fffffffe180 --> 0x1 
0008| 0x7fffffffe118 --> 0x4028e5 (<main+766>:  test   al,al)
0016| 0x7fffffffe120 --> 0x0 
0024| 0x7fffffffe128 --> 0x0 
0032| 0x7fffffffe130 --> 0x0 
0040| 0x7fffffffe138 --> 0x0 
0048| 0x7fffffffe140 --> 0x0 
0056| 0x7fffffffe148 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x00000000004006ca in CheckSolution ()
gdb-peda$ fulldump baby.dump
Filename = baby.dump
Generate a full dump of the current execution
Usage:
    fulldump <filename output>

OK, so no dump file created, unfortunately. And I've opened patched peda.py and start searching for the bug. At least on may machine this line is the problem:

xmm = xmm.splitlines()               # i can print xmm here, no problem
msg(xmm)
xmm = int(xmm[7].split()[2], 16)  # xmm has no value here, problem
msg(xmm)

I've added msg(xmm) lines to find if there is any output. This way, maybe, is so wrong, i don't know but i cannot go further. I cannot get a fulldump of any binary.

JonathanSalwan commented 2 years ago

Hey,

Yeah I got this issue once and it's very weird. This is because the UI of your shell is to small... Yeah I know it makes no sense, but try to define your shell terminal as full screen size. My guess is that if your terminal is to small, the xmm values does not feet in a line and the peda's parsing failed to parse the value...

blue-devil commented 2 years ago

Hey,

Yeah I got this issue once and it's very weird. This is because the UI of your shell is to small... Yeah I know it makes no sense, but try to define your shell terminal as full screen size. My guess is that if your terminal is to small, the xmm values does not feet in a line and the peda's parsing failed to parse the value...

I have the same problem. @JonathanSalwan unfortunately this method is not working.

On the first iteration, after executing this line xmm = xmm.splitlines() xmm variable equals to this:

['xmm0           {',
'  v8_bfloat16 = {0xd7f0, 0xffff, 0x7fff, 0x0, 0xdbf0, 0xffff, 0x7fff, 0x0},',
'  v8_half = {0xd7f0, 0xffff, 0x7fff, 0x0, 0xdbf0, 0xffff, 0x7fff, 0x0},',
'  v4_float = {0xffffd7f0, 0x7fff, 0xffffdbf0, 0x7fff},',
'  v2_double = {0x7fffffffd7f0, 0x7fffffffdbf0},',
'  v16_int8 = {0xf0, 0xd7, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0xf0, 0xdb, '
'0xff, 0xff, 0xff, 0x7f, 0x0, 0x0},',
'  v8_int16 = {0xd7f0, 0xffff, 0x7fff, 0x0, 0xdbf0, 0xffff, 0x7fff, 0x0},',
'  v4_int32 = {0xffffd7f0, 0x7fff, 0xffffdbf0, 0x7fff},',
'  v2_int64 = {0x7fffffffd7f0, 0x7fffffffdbf0},',
'  uint128 = 0x7fffffffdbf000007fffffffd7f0',
'}']

According to the output above:

xmm[7].split()[2] = {0xffffd7f0,

Apparently {0xffffd7f0, is not a number. So int(variable, 16) function fails. That is the problem (I think ?)

if we change lines like below:

change this:
xmm = int(xmm[7].split()[2], 16)

to this:
xmm = int(xmm[7].split()[2].replace('{','').replace(',',''), 16)

Now I can save the dump file. But the size of the dump file is different from yours. For example my baby-re.dump file is bigger than yours, however marsanalytica.dump file is smaller than yours. In those conditions solve scripts for baby-re works but for MarsAnalytica's solve script doesn't work. Solve script for Mars Analytica is ending like this:

<snip>
[+] Starting emulation
[+] 100,000 instructions executed
[+] 200,000 instructions executed
[+] 300,000 instructions executed
[+] 400,000 instructions executed
[+] 500,000 instructions executed
[+] 600,000 instructions executed
[+] 700,000 instructions executed
[+] Serial in construction: ""0000c00090p470```"
[+] Serial in construction: "@00!0!200+0{Y7n00/"
[+] 800,000 instructions executed
[+] 900,000 instructions executed
[+] 1,000,000 instructions executed
[+] Serial in construction: "@@p@=c(`E)`wK!xx^C"
[+] Serial in construction: "#0I00!\0R%>^07jS9~"
[+] Serial in construction: "$'OA?!AkC@Dm"!x=#@"
[+] 1,100,000 instructions executed
[+] 1,200,000 instructions executed
[+] 1,300,000 instructions executed
[+] Serial in construction: "e@M#_!U`#@B~5-sK1("
[+] Serial in construction: "H8p1@y0jBCex6-ww]\"
[+] 1,400,000 instructions executed
[+] Serial in construction: "7Ok0Tc]|.3``(!d}cc"
[+] Serial in construction: "j1{'=cu[EMpx(7|=#>"
[+] Serial in construction: "=B>$Ic_e923yB!ojP~"
[+] Serial in construction: "*Ok.\yM~&,`_0-`gMj"
[+] 1,500,000 instructions executed
[+] 1,600,000 instructions executed
[+] 1,700,000 instructions executed
[+] 1,800,000 instructions executed

[[+] 1,900,000 instructions executed
!] A[+] 2,000,000 instructions executed
CCE[+] 2,100,000 instructions executed
SS [+] 2,200,000 instructions executed
DE[+] 2,300,000 instructions executed
N[+] 2,400,000 instructions executed
[+] 2,500,000 instructions executed
I[+] 2,600,000 instructions executed
ED [+] 2,700,000 instructions executed
- In[+] 2,800,000 instructions executed
val[+] 2,900,000 instructions executed
id[+] 3,000,000 instructions executed
 C[+] 3,100,000 instructions executed
itiz[+] 3,200,000 instructions executed
en[+] 3,300,000 instructions executed
<snip>

I think i couldn't fix the peda patch :/ Any help is welcome

JonathanSalwan commented 2 years ago

God, I've just checked my peda.py file and just saw that i've commented those lines:

6027         # XMM                                                                   
6028         #arch, bits = peda.getarch()                                            
6029         #cnt = (8 if bits == 32 else 16)                                        
6030         #for i in range(cnt):                                                   
6031         #    xmm = peda.execute_redirect("info registers xmm%d" % (i))          
6032         #    xmm = xmm.splitlines()                                             
6033         #    xmm = int(xmm[7].split()[2], 16)                                   
6034         #    regs.update({"xmm%d" % (i): xmm}

My solution here was probably for years ago and now there is another issue where I ignored it by commenting those line...

I will try to fix it.

JonathanSalwan commented 2 years ago

Below the new peda patch which will fix this issue:

diff --git a/peda.py b/peda.py
index 14a7f5e..215ce3e 100644
--- a/peda.py
+++ b/peda.py
@@ -5998,6 +5998,52 @@ class PEDACmd(object):
         return
     utils.options = ["int2hexstr", "list2hexstr", "str2intlist"]

+    def fulldump(self, *arg):
+        """
+        Generate a full dump of the current execution
+        Usage:
+            fulldump <filename output>
+        """
+        (filename,) = normalize_argv(arg, 1)
+        if not filename:
+            filename = "fulldump.dump"
+
+        pid = peda.getpid()
+        if not pid:
+            return False
+
+        maps = peda.get_vmmap()
+        if not maps:
+            return False
+
+        memory = list()
+        for s, e, x, f in maps:
+            raw  = peda.dumpmem(s, e)
+            memory.append({"start": s, "end": e, "memory": raw, "permissions": x, "name": f})
+
+        # GPR
+        regs = peda.getregs()
+
+        # XMM
+        arch, bits = peda.getarch()
+        cnt = (8 if bits == 32 else 16)
+        for i in range(cnt):
+            xmm = peda.execute_redirect("info registers xmm%d" % (i))
+            offset = xmm.find('uint128')
+            if offset > 0:
+                uint128 = xmm[offset:].replace('\n', '').replace('}', '').split('=')[1]
+                regs.update({"xmm%d" % (i): int(uint128, 16)})
+
+        dump = (regs, memory)
+
+        fd = open(filename, "w")
+        fd.write(repr(dump))
+        fd.close()
+
+        msg("Full dump saved into %s" % (filename))
+
+        return True
+
 ###########################################################################
 class pedaGDBCommand(gdb.Command):
     """

I've tested with baby-re and MarsAnalytica and it looks like to work.

JonathanSalwan commented 2 years ago

@blue-devil, @0xFF1E071F, can you test the new patch and tell me if it solves the issue on your side too?

blue-devil commented 2 years ago

@JonathanSalwan problem is fixed for me. I have checked for both binaries, baby-re and MarsAnalytica. fulldump created without problem, and i also checked the solve scripts. They are also working!

Note on MarsAnalytica: How the did you find/calculate this address -0xc4d42a- on line or instruction.getAddress() == 0xc4d42a: I couldn't understand?

Thank you very much Jonathan; you have spent your time on this weekend!

JonathanSalwan commented 2 years ago

Note on MarsAnalytica: How the did you find/calculate this address -0xc4d42a- on line or instruction.getAddress() == 0xc4d42a: I couldn't understand?

At the beginning, the script was executing the full trace but when I understood that I found the good serial, I just piked up a random address to define it as an end point of execution. You can remove it if you want and it will execute the full trace and prints "Access Granted". But as it takes time to execute I just used this address to stop the execution in order to speedup my unittests workflow.

0xFF1E071F commented 2 years ago

@JonathanSalwan +1 I have tried the new patch and it is working. Thank you very much, you can close the issue.

Close 1143