radareorg / radare2

UNIX-like reverse engineering framework and command-line toolset
https://www.radare.org/
GNU Lesser General Public License v3.0
20.73k stars 3.01k forks source link

Simplify the way pe resources are extracted #16326

Open radare opened 4 years ago

radare commented 4 years ago

Reference tweet: https://twitter.com/defconisov3r/status/1242240569667174400?s=21

0v3rflow1 commented 4 years ago

The main objective is to get all the resources of a file quickly using a simple command. In the first instance I have tried to recover them using rabin2 -x, but it did not work, investigating a little I managed to get to the rabin2 -O d/S/.rsrc file > resources.dump command. Which gives me a general dump of the entire resources section (Useful but not comfortable for the individual analysis of each of the resources).

Seeing myself in this trouble I have chosen to use r2pipe as recommended by @trufae ...

This is what I have achieved so far (It is the first time I use r2pipe) :P

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import r2pipe
import sys
import re

path=sys.argv[1];
r2 = r2pipe.open(path);
vaddrs=r2.cmd('iR~vaddr');
vaddrs=re.sub(r'(vaddr|:| )','', vaddrs);
vaddrs=re.split('\s',vaddrs);
l=len(vaddrs)-2;
print("El fichero contiene "+str(l)+" recursos");
i=0;
j=1;
while(l>i):
        print("Distancia "+str(j));
        a=int(vaddrs[l],16);
        b=int(vaddrs[l-1],16);
        c=a-b;
        print(hex(a)+"-"+hex(b)+"="+str(c));
        print(r2.cmd("px"+str(c)+"@"+str(b)));
        l-=1;
        j+=1;
0v3rflow1 commented 4 years ago

An improved version of this little script would be this one... It already saves the content of each resource in a ".bin" file for further analysis individually :).

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import r2pipe
import sys
import re

path=sys.argv[1];
r2 = r2pipe.open(path);

vaddrs=r2.cmd('iR~vaddr');
vaddrs=re.sub(r'(vaddr|:| )','', vaddrs);

sizes=r2.cmd('iR~size');
sizes=re.sub(r'(size|:| )','', sizes);

vaddrs=re.split('\s',vaddrs);
sizes=re.split('\s',sizes);

l=len(vaddrs)-1;
print("El fichero contiene "+str(l)+" recursos");
i=0;
while(i<l):
        size=r2.cmd("? "+sizes[i]+"~uint32");
        size=re.sub(r'(uint32|\s)','', size);
        a=vaddrs[i];
        a=hex(int(vaddrs[i],16));
        b=hex(int(vaddrs[i],16)+int(size));
        print("\nRecurso #"+str(i+1)+"\n"+"="*15+"\n");
        print("Size: "+size);
        print("Inicia en: "+a);
        print("Termina en: "+b);
        strBin=r2.cmd("pcs "+str(size)+"@"+str(a));
        buf=eval(strBin);
        f= open("res"+str(i)+".bin","w+");
        f.write(buf);
        f.close();
        print("Fichero de salida: res"+str(i)+".bin");
        i+=1;

imagen

0v3rflow1 commented 2 years ago

radare2 do not list the ordered resources based on your VADDR (or at least it does not for 1BC44EF75779E3CA1EFBC942B1E4A267D292591) and I had not noticed.

This is a correction that considers this inconvenient and obtains the list of resources with a better precision.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import r2pipe
import sys
import re
import codecs

path=sys.argv[1];
r2 = r2pipe.open(path);

vaddrs=r2.cmd('iR~vaddr|sort');
vaddrs=re.sub(r'(vaddr|:| )','', vaddrs);
vaddrs=re.split('\s',vaddrs);

l=len(vaddrs)-1;

print("El fichero contiene "+str(l)+" recursos");

i=0;
while(i<l):
        name=r2.cmd('iR|grep -A 3 -B 3 '+vaddrs[i]+'|grep -Eio "name.*"');
        name=re.sub(r'(name|:| )','',name).rstrip('\n');
        size=r2.cmd('iR|grep -A 3 -B 3 '+vaddrs[i]+'|grep -Eio "size.*"');
        size=re.sub(r'(size|:| )','',size).rstrip('\n');
        a=vaddrs[i];
        a=hex(int(a,16));
        if(i!=(l-1)):
          b=hex(int(vaddrs[i+1],16));
          size=hex(int(b,16)-int(a,16));
        else:
            size=r2.cmd("? "+size+"~uint32");
            size=re.sub(r'(uint32|\s)','', size);
            b=hex(int(a,16)+int(size));

        print("\nRecurso #"+str(i)+"\n"+"="*15+"\n");
        print("Name: "+name);
        print("Size: "+size);
        print("Inicia en: "+a);
        print("Termina en: "+b);

        strBin=r2.cmd("pcs "+str(size)+"@"+str(a));
        buf=eval(strBin.encode('utf8'));
        f= codecs.open("res_"+str(name)+".bin","w+","utf-8");
        f.write(buf);
        f.close();
        print("Fichero de salida: res_"+str(name)+".bin");
        i+=1;
trufae commented 2 years ago

This seems like a good candidate for

https://github.com/radareorg/r2pipe-codeshare