Is there any way to disassemble windows exe files in linux?
Would this involve Wine? If so, is there any windows debug/disassembly program available for linux?
And can this be done with gdb?
Thnx.
objdump -d works for me (I have version 2.24):
$ objdump -d ~/.wine/drive_c/Program\ Files\ \(x86\)/Internet\ Explorer/iexplore.exe |head
/home/user/.wine/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe: file format pei-i386
Note that I tried other binaries, including ntoskrnl.exe and Steam.exe and they also work with objdump
Disassembly of section .text:
10001000 <.text>:
10001000: b8 01 00 00 00 mov $0x1,%eax
10001005: c2 04 00 ret $0x4
For me, gdb didn't work, even when running with wine:
/home/user/.wine/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe: not an ELF binary... don't know how to load it
Check out IDA Debugger Used it in the past with success.
Related
If I run objdump -d on a (linux amd64) .o file, function calls show up without the link time resolution done. Example:
90: 66 89 44 24 1c mov %ax,0x1c(%rsp)
95: 44 89 74 24 10 mov %r14d,0x10(%rsp)
9a: e8 00 00 00 00 callq 9f <foo+0x9f>
9f: 83 f8 ff cmp $0xffffffffffffffff,%eax
a2: 74 5e je 102 <foo+0x102>
A branch within the function shows up properly, but the callq is just the stub put in for the linker (with four bytes of zeros available for the linker to put a proper address into).
Is there a way, without actually linking, to get an assembly listing that has the function names resolved? I don't care about the address that will eventually be used, just the name of the function. That info has got to be in the .o file, since the linker must consume it to do its job.
I ask because the shared lib that the code in question goes into is about 140Mb, and it takes a long time to run objdump -d on that to get the asm dump with all the function calls resolved to their actual names.
Is there a way, without actually linking, to get an assembly listing that has the function names resolved?
Yes: use objdump -dr foo.o
Objdump can figure out when the binary is calling GLIBC functions, like printf:
$ objdump -d crackme03.64 -Mintel | grep printf
5c8: ff 25 12 0a 20 00 jmp QWORD PTR [rip+0x200a12] #200fe0 <__printf_chk#GLIBC_2.3.4>
However, looking at the same address, Radare is much less helpful:
[0x000005c8]> pd 2
/ (fcn) sub.__cxa_finalize_224_5c8 8
| sub.__cxa_finalize_224_5c8 ();
| ; CALL XREF from 0x000007bc (sym.main)
| ; CALL XREF from 0x00000809 (sym.main)
| 0x000005c8 ff25120a2000 jmp qword [reloc.__cxa_finalize_224] ; [0x200fe0:8]=0 LEA reloc.__cxa_finalize_224 ; reloc.__cxa_finalize_224
\ 0x000005ce 6690 nop
Is there a way to ask Radare to figure out what these functions correspond to?
It should work if you're using the newest version from git.
Radare2’s development is pretty quick – the project evolves every day, therefore it’s recommended to use the current git version. Update your version and it should solve your problem:
$ git clone https://github.com/radare/radare2.git
$ cd radare2
$ ./sys/install.sh
In the opensource code of OpenSSL(version 1.1.0e) I saw that some of the function definition is generated by the perl files present inside the folders.
In the build.info file present in each folders inside the crypto, they have written some lines to generate the .s from the corresponding .pl.
For example, for generating aes_p8_set_encrypt_key in crypto/aes/build.info:
GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME)
for generating OPENSSL_madd300_probe in crypto/build.info :
GENERATE[ppccpuid.s]=ppccpuid.pl $(PERLASM_SCHEME)
And also in the main Makefile(generated makefile), there are some lines as below:
crypto/aes/aes-x86_64.o: crypto/aes/aes-x86_64.s
$(CC) -I. -Icrypto/include -Iinclude $(CFLAGS) $(LIB_CFLAGS) -MMD -MF crypto/aes/aes-x86_64.d.tmp -MT $# -c -o $# crypto/aes/aes-x86_64.s
#touch crypto/aes/aes-x86_64.d.tmp
#if cmp crypto/aes/aes-x86_64.d.tmp crypto/aes/aes-x86_64.d > /dev/null 2> /dev/null; then \
rm -f crypto/aes/aes-x86_64.d.tmp; \
else \
mv crypto/aes/aes-x86_64.d.tmp crypto/aes/aes-x86_64.d; \
fi
Followed with :
crypto/aes/aes-x86_64.s: crypto/aes/asm/aes-x86_64.pl
CC="$(CC)" $(PERL) crypto/aes/asm/aes-x86_64.pl $(PERLASM_SCHEME) $#
Can anyone explain how the .s is generated from the .pl files?
I need to add them in my Makefile inside my project, to solve the undefined reference error coming for the functions whose definition is generated by the .pl file.
How the assembly file is generated from the Perl script in OpenSSL...
You are using the Cryptogams implementation of AES on Power8. Cryptogams is Andy Polyakov's project to provide high speed cryptography to other developers.
The assembly language file is generated with a xlat program. For the Power8 gear the file is ppc-xlate.pl in the perlasm directory. It is used by aesp8-ppc.pl in the crypto/aes/asm directory.
Here is how you translate it. I'm working from GCC112 on the compile farm, which is ppc64le.
git clone https://github.com/openssl/openssl.git
mkdir cryptogams
cp ./openssl/crypto/perlasm/ppc-xlate.pl cryptogams/
cp ./openssl/crypto/aes/asm/aesp8-ppc.pl cryptogams/
cd cryptogams/
chmod +x *.pl
./aesp8-ppc.pl ppc64le aesp8-ppc.s
aesp8-ppc.pl generates a pure assembly language source file so name the output file with the little *.s. Sometimes the translation includes C preprocessor statements and it needs a big *.S (but not in this case).
The second argument to aesp8-ppc.pl is called flavor. It is ppc64le in the commands above. Flavor does two things. First, it selects either 32-bit or 64-bit. Second, it selects either little-endian or big-endian. Be sure to get the flavor right.
According to Andy at ppc8 does not build on powerpc64 big-endian, big-endian PowerPC should use linux64, not linux64be. Little-endian needs linux64le, however.
Once you have aesp8-ppc.s you can compile and assemble the source file with GCC.
gcc -mcpu=power8 -c aesp8-ppc.s
And then:
$ objdump --disassemble aesp8-ppc.o
aesp8-ppc.o: file format elf64-powerpcle
...
0000000000000420 <aes_p8_set_decrypt_key>:
420: c1 ff 21 f8 stdu r1,-64(r1)
424: a6 02 48 7d mflr r10
428: 50 00 41 f9 std r10,80(r1)
42c: 75 fc ff 4b bl a0 <aes_p8_set_encrypt_key>
430: a6 03 48 7d mtlr r10
434: 00 00 03 2c cmpwi r3,0
438: 68 00 c2 40 bne- 4a0 <Ldec_key_abort>
43c: 36 20 07 55 rlwinm r7,r8,4,0,27
440: 10 ff 65 38 addi r3,r5,-240
444: 7e f8 08 55 rlwinm r8,r8,31,1,31
448: 14 3a a3 7c add r5,r3,r7
44c: a6 03 09 7d mtctr r8
...
At this point you have an object file, but you don't know the API signatures or how to use it. To find out what to do next you have to objdump and then grep the OpenSSL sources to see how they use it.
$ nm aesp8-ppc.o | grep ' T '
00000000000006c0 T aes_p8_cbc_encrypt
0000000000001140 T aes_p8_ctr32_encrypt_blocks
00000000000005c0 T aes_p8_decrypt
00000000000004c0 T aes_p8_encrypt
0000000000000420 T aes_p8_set_decrypt_key
00000000000000a0 T aes_p8_set_encrypt_key
0000000000001d00 T aes_p8_xts_decrypt
0000000000001a60 T aes_p8_xts_encrypt
You are interested in the four functions aes_p8_set_encrypt_key, aes_p8_set_decrypt_key, aes_p8_encrypt and aes_p8_decrypt. You will use the signatures you find to create a header file for your program.
I'll help you with the first one: aes_p8_set_encrypt_key.
$ cd openssl
# Find aes_p8_set_encrypt_key
$ grep -nIR aes_p8_set_encrypt_key
crypto/evp/e_aes.c:153:# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
# Now look for HWAES_set_encrypt_key
$ grep -nIR HWAES_set_encrypt_key
...
crypto/evp/e_aes.c:2515:int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
...
# Now find the complete HWAES_set_encrypt_key
$ cat -n crypto/evp/e_aes.c
...
2515 int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
2516 AES_KEY *key);
Lather, rinse, repeat for AES_KEY, aes_p8_set_decrypt_key, aes_p8_encrypt and aes_p8_decrypt.
Eventually you will end up with a header like shown in Cryptogams | AES or Cryptogams | SHA on the OpenSSL wiki. Cryptogams | AES and Cryptogams | SHA are written for ARMv4 but the same applies to Power8 as well.
Andy dual licenses his work. One license is the OpenSSL license because Andy works for OpenSSL. The second license is a BSD style license that does not have the encumbrances of OpenSSL.
Andy's public source is at GitHub | dot-asm. Unfortunately, a lot of Andy's work has not been uploaded so you have to pull it from OpenSSL. And a lot it is not documented so you have to do a fair amount of poking and prodding in the OpenSSL sources.
As far as I know there are two places you can look for documentation on using Cryptogams and Power8 cryptography. First is the OpenSSL wiki pages Cryptogams | AES and Cryptogams | SHA. The tutorials are ARMv4 but it applies to Power 8, too. I wrote the wiki articles so errors and omissions are my mistakes.
The second place to look is GitHub and Noloader | POWER8 crypto. I help maintain Crypto++ and the POWER8 crypto book is my knowledge dump. The POWER8 book includes Cryptogams SHA for PowerPC in Chapter 7.
The POWER8 crypto book was written by Bill Schmidt and I because we could not find documentation when working with AES and SHA on Power8. Bill Schmidt works for IBM and even he could not get the docs. All we could find was a blog post from an IBM engineer that was grossly missing details.
I have written simple Hello world program and compiled it with gcc-arm-linux-gnueabi compiler. It compiles well but when i try to execute it on ARM machine it complains "no such file or directory". I think gcc-arm-linux-gnueabi is for embedded Linux only due to e(mbedded)abi. Is it different from ARM Linux ABI?
Please help me to solve this problem
code is here
#include "stdio.h"
int main(void) {
printf("Hello world !\n");
return 0;
}
compiled as
arm-linux-gnueabi-gcc -Wall -o crosscomp hello.c
When i execute this crosscomp on target ARM machine error is crosscomp no such file or dir
EDIT When I was using arm-linux-gnueabi-gcc the entry point was not matching with the target machine entry point (readelf -l crosscom) but when I compiled with aarch64-linux-gnu-gcc entry point matched with target machine. But now error becomes permission denied on ./crosscomp. I tried with sudo which says crosscomp: no such command.
Note I posted same question on askubuntu https://askubuntu.com/questions/904685/cross-compilation-for-arm-error-no-such-file-or-directory but got no response.
The output of readelf is as below
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: AArch64
Version: 0x1
Entry point address: 0x400470
Start of program headers: 64 (bytes into file)
Start of section headers: 4488 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 26
This peculiar error message happens when the dynamic loader required by a particular executable is missing.
You can find out the name of the dynamic loader that you need by applying readelf to the problem executable. On my x86-64 Linux box, for example
$ readelf -l /bin/ls | grep 'program interpreter'
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
("program interpreter" is another name for "dynamic loader".)
So, run the above command on your crosscomp binary on your development box. (If you don't have readelf or you get error messages, try arm-linux-gnueabi-readelf.) The file named after "program interpreter:" needs to exist on your target ARM machine. If you don't know where to get it, please post the output of the above command + ls -l of the directory that should have the missing file in it.
As I know basic difference between bin and elf that
Bin file contain only bit or bytes of data and you need to give address of memory when you load it in memory,
while in case of elf it have symbol look-ups and relocatable table, so no need to give address when you program it.
Now see attached image. I am using LPCexpresso to program elf file in device. if you not give base address then it will take 0x00000000 by default. Now i first programme bootloader.elf and then main.elf. in both case I am not giving base address.
Now my question is if I am not giving address then how elf file decide to program correct location and after programming one image if I programme another image then isn't it overwrite first one? (because in both case we haven't give address and by default it 0x00000000)
Normally this information is inside the ELF file created by the linker script.
As part of the GNU binutils, there is a tool called "readelf", that shows information about the ELF sections and headers. Unfortunatelly these tools uses to have a prefix depending on its configuration tool, most likely it will be called "arm-none-readelf". If you do not have it, checkout http://www.yagarto.org/
So, if you type "arm-none-readelf main.elf -a" it should show something like:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: YOUR ARCHITECTURE
Version: 0x1
Entry point address: YOUR ENTRY ADDRESS
Start of program headers: 52 (bytes into file)
Start of section headers: YOUR SIZE
Flags: 0x300
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 36
Size of section headers: 40 (bytes)
Number of section headers: 55
Section header string table index: 52
(Please note that this is just example data).
Normally in all the compiler there are options for the linker that allows to specify the load address of your ELF, (uses to be called .ld file).
Hope it helps.