1

the experiment is on Linux, x86 32-bit.

So suppose in my assembly program, I need to periodically (for instance every time after executing 100000 basic blocks) dump an array in .bss section from memory to the disk. The starting address and size of the array is fixed. The array records the executed basic block's address, the size is 16M right now.

I tried to write some native code, to memcpy from .bss section to the stack, and then write it back to disk. But it seems to me that it is very tedious and I am worried about the performance and memory consumption, say, every-time allocate a very large memory on the stack...

So here is my question, how can I dump the memory from global data sections in an efficient way? Am I clear enough?

3 Answers 3

1

In case of IdaPro being available - it works on Linux as well - you could consider using an Ida script, like this:

    static main()
    {
        DumpMem();
    }


    static DumpMem()
    {
        auto h;
        auto ea;
        auto eaStart = <here your start address>;
        Message("dumping...");
        h = fopen("dumped.bin", "wb");
        for (ea=eaStart; ea<eaStart+0x100000; ea=ea+1)
        {
            fputc(Byte(ea), h);
        }
        fclose(h);
        Message("done!\n");
    }

The use would be like this:

  1. Copy and paste the above code into a file with the .idc extension, write the memory address into it.

  2. Put a breakpoint where you need the dump

  3. When the BPt triggers, in Ida, from Menu File, Script File ... select your idc file.

2
  • Thank you. But actually I didn't know at which point it would be triggered. Suppose I insert some instrumentation code at the beginning of every basic blocks. And I need to dump the memory when, say, 100000 basic blocks have been executed.. Commented Jul 16, 2015 at 17:05
  • Sorry, the timeout prevented me from editing the last comment. In my understanding, you could write in your "instrumentation code" some logic like the one in my Ida script, enhancing it with a block counter and triggering the file write only when that counter reaches the requested value. A free memory area could hold the counter. I hope I understood you right.
    – josh
    Commented Jul 16, 2015 at 17:16
1

I don't see a reason why you shouldn't be able to dump a block to the disk from the stack directly.

Starting with

#include <fcntl.h>

char *block;

int main(void) {
    int fd=open("/tmp/myfile", O_WRONLY|O_APPEND|O_CREAT, 0666);
    write(fd, block, 0x400000);
    close(fd);
}

and continuing with

gcc -m32 -S b.c

you arrive at this b.s file

.LC0:
    .string "/tmp/myfile"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $438, 8(%esp)
    movl    $1089, 4(%esp)
    movl    $.LC0, (%esp)           <--- make sure this is the filename string
    call    open
    movl    %eax, 28(%esp)
    movl    block, %eax             <--- and this is the address of your buffer
    movl    $4194304, 8(%esp)
    movl    %eax, 4(%esp)
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    write
    movl    28(%esp), %eax
    movl    %eax, (%esp)
    call    close
    leave
    ret

which you could copy to your instrumentation with very few modifications. (You'll probably want to save a few registers and restore them on exit).

Or, compile the program using gcc -static -m32 b.c and objdump -d the resulting executable to find out how the system calls are implemented, then replace the library calls with the direct system calls. This has the additional advantage that you don't have to mess with import lists if your instrumentation modifies a completed executable file.

<push registers you want to save>
mov  $438, %edx
mov  $1089, %ecx
mov  filename, %ebx
mov  $0x5, %eax      ;5 is system call # for open
call *0x80d66c4      ;this is the system call address pulled from objdump
mov  %eax, %esi      ;save fd
mov  $0x400000, %edx
mov  block, %ecx     ;your buffer address
mov  %eax, %ebx
mov  $0x4, %eax      ;4 is system call # for write
call *0x80d66c4
mov  %esi, %ebx
mov  $0x6, eax       ;6 is system call # for close
call *0x80d66c4
<pop registers>

This doesn't do any error checking, but you should be ok if you put the file on a local hard disk that has enough space. Also, it appends to the file every time instead of creating it, so you'll have to rm the file before each run.

1

with gdb you can define a canned sequence and execute it
a sample canned sequence could be

stepi {count} append memory {filepath} {start} {end}

a sample run on cygwin gdb over gdb

$ gdb gdb
GNU gdb (GDB) Cygwin 7.9.1-1

(gdb) define dumpy
Type commands for definition of "dumpy".
End with a line saying just "end".
>si 10000
>append value ../../cygdrive/c/tmp/dumpy.txt $pc
>append memory ../../cygdrive/c/tmp/dumpy.txt $pc $pc+4
>end
(gdb) break *0x401000
Breakpoint 1 at 0x401000
(gdb) r
Starting program: /usr/bin/gdb
[New Thread 3300.0xe20]

Breakpoint 1, 0x00401000 in ?? ()
(gdb) dumpy
[New Thread 3300.0xbc0]
0x610bf987 in auto_protect_for(void*) () from /usr/bin/cygwin1.dll

(gdb) x/x $pc
0x610bf987 <_ZL16auto_protect_forPv+135>:       0x05f6e572      

(gdb) dumpy
0x610f007b in sys_cp_wcstombs(int (*)(_reent*, char*, wchar_t, char const*, _mbstate_t*), char const*, char*, unsigned int, wchar_t const*, unsigned int) ()
   from /usr/bin/cygwin1.dll


(gdb) dumpy
0x610f0028 in sys_cp_wcstombs(int (*)(_reent*, char*, wchar_t, char const*, _mbstate_t*), char const*, char*, unsigned int, wchar_t const*, unsigned int) ()
   from /usr/bin/cygwin1.dll
(gdb)

xxd doesnt convert endianness so i cooked a powershell script to dump the dumpy.txt

$file = gc -encoding byte $args[0]
$j=0
while($j-lt $file.length) {
$i=$j;$a="";($i+3)..($i+0)|%{$a+=("{0:x2}" -f $file[$_])};$a+=" ";
$i=$i+4;($i+3)..($i+0)|%{$a+=("{0:x2}" -f $file[$_])};
$a
$j+=8
}

dumping the dumpy.txt as address , content pairs with the powershell script above you can see it matches gdb output

PS C:\tmp> powxxd.ps1 .\dumpy.txt
610bf987 05f6e572
610f007b f6851f74
610f0028 2c24448b

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.