Archive for September, 2010

ndisasm is more useful than objdump sometimes

First, Let’s check out the manual page for ndisasm,

NDISASM(1)

NAME
ndisasm – the Netwide Disassembler, an 80×86 binary file disassembler

SYNOPSIS
ndisasm  [  -o  origin  ]  [ -s sync-point […]]  [ -a | -i ] [ -b bits ] [ -u ] [ -e hdrlen ] [ -k offset,length
[…]]  infile
ndisasm -h
ndisasm -r

DESCRIPTION
The ndisasm command generates a disassembly listing of the binary file infile and directs it to stdout.

OPTIONS
-h     Causes ndisasm to exit immediately, after giving a summary of its invocation options.

-r     Causes ndisasm to exit immediately, after displaying its version number.

-o origin
Specifies the notional load address for the file. This option causes ndisasm to get the addresses it  lists
down the left hand margin, and the target addresses of PC-relative jumps and calls, right.

-s sync-point
Manually  specifies  a  synchronisation  address, such that ndisasm will not output any machine instruction
which encompasses bytes on both sides of the address. Hence the instruction which starts  at  that  address
will be correctly disassembled.

-e hdrlen
Specifies  a  number  of  bytes to discard from the beginning of the file before starting disassembly. This
does not count towards the calculation of the disassembly offset: the first disassembled  instruction  will
be shown starting at the given load address.

-k offset,length
Specifies that length bytes, starting from disassembly offset offset, should be skipped over without gener‐
ating any output. The skipped bytes still count towards the calculation of the disassembly offset.

-a or -i
Enables automatic (or intelligent) sync mode, in which ndisasm will attempt to guess where  synchronisation
should  be  performed, by means of examining the target addresses of the relative jumps and calls it disas‐
sembles.

-b bits
Specifies 16-, 32- or 64-bit mode. The default is 16-bit mode.

-u     Specifies 32-bit mode, more compactly than using `-b 32′.

-p vendor
Prefers instructions as defined by vendor in case of a conflict.  Known vendor names  include  intel,  amd,
cyrix, and idt.  The default is intel.

RESTRICTIONS
ndisasm  only  disassembles  binary  files: it has no understanding of the header information present in object or
executable files. If you want to disassemble an object file, you should probably be using objdump(1).

Auto-sync mode won’t necessarily cure all your synchronisation problems: a sync marker can only be placed automat‐
ically if a jump or call instruction is found to refer to it before ndisasm actually disassembles that part of the
code. Also, if spurious jumps or calls result from disassembling  non-machine-code  data,  sync  markers  may  get
placed in strange places. Feel free to turn auto-sync off and go back to doing it manually if necessary.

While I was trying to dump the content of memory maps(/proc/pid/maps) in process, I found that some codes are dumped out but cannot be analyzed using the “objdump”, using “ndisasm” can get the assembly code displayed even file is not in “ELF” format.

Let’s checkout the memory maps for “cat” on my x86_64 pc,

# cat /proc/self/maps
00400000-0040d000 r-xp 00000000 07:00 652826                             /bin/cat
0060d000-0060e000 r–p 0000d000 07:00 652826                             /bin/cat
0060e000-0060f000 rw-p 0000e000 07:00 652826                             /bin/cat
01ba7000-01bc8000 rw-p 00000000 00:00 0                                  [heap]
7f151370b000-7f1513885000 r-xp 00000000 07:00 666978                     /lib/libc-2.11.1.so
7f1513885000-7f1513a84000 —p 0017a000 07:00 666978                     /lib/libc-2.11.1.so
7f1513a84000-7f1513a88000 r–p 00179000 07:00 666978                     /lib/libc-2.11.1.so
7f1513a88000-7f1513a89000 rw-p 0017d000 07:00 666978                     /lib/libc-2.11.1.so
7f1513a89000-7f1513a8e000 rw-p 00000000 00:00 0
7f1513a8e000-7f1513aae000 r-xp 00000000 07:00 661089                     /lib/ld-2.11.1.so
7f1513b33000-7f1513b72000 r–p 00000000 07:00 1052479                    /usr/lib/locale/en_US.utf8/LC_CTYPE
7f1513b72000-7f1513c90000 r–p 00000000 07:00 1052374                    /usr/lib/locale/en_US.utf8/LC_COLLATE
7f1513c90000-7f1513c93000 rw-p 00000000 00:00 0
7f1513c9b000-7f1513c9c000 r–p 00000000 07:00 1052380                    /usr/lib/locale/en_US.utf8/LC_NUMERIC
7f1513c9c000-7f1513c9d000 r–p 00000000 07:00 1065267                    /usr/lib/locale/en_US.utf8/LC_TIME
7f1513c9d000-7f1513c9e000 r–p 00000000 07:00 1065268                    /usr/lib/locale/en_US.utf8/LC_MONETARY
7f1513c9e000-7f1513c9f000 r–p 00000000 07:00 1065269                    /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
7f1513c9f000-7f1513ca0000 r–p 00000000 07:00 1052589                    /usr/lib/locale/en_US.utf8/LC_PAPER
7f1513ca0000-7f1513ca1000 r–p 00000000 07:00 1052262                    /usr/lib/locale/en_US.utf8/LC_NAME
7f1513ca1000-7f1513ca2000 r–p 00000000 07:00 1065270                    /usr/lib/locale/en_US.utf8/LC_ADDRESS
7f1513ca2000-7f1513ca3000 r–p 00000000 07:00 1065271                    /usr/lib/locale/en_US.utf8/LC_TELEPHONE
7f1513ca3000-7f1513ca4000 r–p 00000000 07:00 1052585                    /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
7f1513ca4000-7f1513cab000 r–s 00000000 07:00 1046975                    /usr/lib/gconv/gconv-modules.cache
7f1513cab000-7f1513cac000 r–p 00000000 07:00 1065272                    /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
7f1513cac000-7f1513cae000 rw-p 00000000 00:00 0
7f1513cae000-7f1513caf000 r–p 00020000 07:00 661089                     /lib/ld-2.11.1.so
7f1513caf000-7f1513cb0000 rw-p 00021000 07:00 661089                     /lib/ld-2.11.1.so
7f1513cb0000-7f1513cb1000 rw-p 00000000 00:00 0
7fffd88a3000-7fffd88b8000 rw-p 00000000 00:00 0                          [stack]
7fffd89ff000-7fffd8a00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Here is the code I used to dump the content of memory maps(for vdso, vsyscall, etc.)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define MEM_MAP “/proc/self/maps”
#define OUTPUT_FILE “output.dump”
#define LINE_MAX 4096

int main(int argc, char *argv[])
{
FILE *dev_maps, *out_file;
char line_buf[LINE_MAX], map_name[LINE_MAX];
char addr_string[64] = {0};
int offset, inode;
size_t ret;
char perms[4] = {0};
char dev[8] = {0};
char *lib_buf;
unsigned long start_addr, end_addr;

if ((out_file = fopen(OUTPUT_FILE, “w”)) == NULL)
{
fprintf(stderr, “open output file error\n”);
return 1;
}

if ((dev_maps = fopen(MEM_MAP, “r”)) == NULL)
{
fprintf(stderr, “read mem map file err!\n”);
return 1;
}

while (!feof(dev_maps))
{
if (fgets(line_buf, LINE_MAX, dev_maps) != NULL)
{
if (sscanf(line_buf, “%s %s %d %s %d %s\n”,
addr_string, perms, &offset,
dev, &inode, map_name) == 6)
{
printf(“%s, %s, %d, %s, %d, %s\n”,
addr_string, perms, offset, dev, inode, map_name);

start_addr = strtoul(strtok(addr_string, “-“), NULL, 16);
end_addr = strtoul(strtok(NULL, “-“), NULL, 16);
if (strcmp(map_name, argv[1]) == 0)
{
lib_buf = (char *)malloc(end_addr – start_addr);
memcpy(lib_buf, (const void *)start_addr, end_addr – start_addr);
fwrite(lib_buf, end_addr – start_addr, 1, out_file);
free(lib_buf);
}
}
}
}
fclose(dev_maps);
fclose(out_file);
return 0;
}

I used memcpy in code, we can also read /proc/self/mem device to get the memory content.

Now I compile it,

#gcc -m64 -o memcontent memcontent.c

#./memcontent [vsyscall]

#file output.dump

output.dump: data

Then we can use ndisasm to check the output.dump for vsyscall in memory map,

#ndisasm -b 64 -p amd output.dump > test.s

Now we can dump the code of the “vsyscall_64.o” which is generated during making 64 bit kernel,

#objdump -d vsyscall_64.o > test1.s

After this we can check the different between test.s and test1.s, to me, it is almost the same, which means ndisasm does a good job, and “[vsyscall]” map is a mapping for “vsyscall_64.o”.

You can also try to dump other parts like “[vdso]”, or “ld-*.so” “libc-*.so”, and check their contents, have fun!

Leave a comment

Interesting…

Just switch from msn spaces to wordpress, interesting…

Leave a comment

What Inception reminds me of?

Assassin Creed 2

1 Comment