I am a beginner in low level programming and I am playing with Nasm under linux.
The purpose of the following code is to copy some code on the heap (using linux syscall brk) and jump to it.
Once running the code from the heap, the program simply prints out a message and returns to the address on top of the stack.
The problem I have depends on how I print the message. If I use a syscall, it works, but if I use a printf libc call, it fails.
The only thing I can get from GDB is :
Program received signal SIGSEGV, Segmentation fault.
0x08049f3d in _DYNAMIC ()
The buggy code is located after the inject label.
Do you have any idea, why the libc call is failling?
Thanks.
Code: Select all
segment .data
msg1 db "Retrieving BRK value...", 10, 0
len equ $-msg1
ptrval db "Found brk(0) = %p", 10, 0
junkval db " junk = %p", 10, 0
dump db " dump : %p", 10, 0
injection db "Injection complete, reading code from heap!", 10, 0
injectionlen equ $-injection
injectsize db "Code injection requires %d bytes...", 10, 0
backloop db "Now, back in the loop.", 10, 0
dbg db "ebx=%d, cond=%d", 10, 0
segment .bss
junk resd 1
ptr resd 1
ptr2 resd 1
segment .text
global main
extern printf
main:
enter 0,0 ; setup routine
pusha
; Show msg1
mov edx, len
mov ecx, msg1
mov ebx, 1 ; fd = 1 = stdout
mov eax, 4 ; 4 = linux write system call
int 0x80 ; syscall software interrupt
; get brk
mov ebx, 0 ; 0 to get current brk pointer
mov eax, 45 ; 45 = linux brk system call
int 0x80 ; syscall software interrupt
mov [ptr], eax ; store brk(0) in ptr
push eax
push dword ptrval
call printf
pop ecx
pop ecx
push junk
push dword junkval
call printf
pop ecx
pop ecx
mov eax, [ptr]
push eax
push dword ptrval
call printf
pop ecx
pop ecx
mov eax, $skip-$inject
push eax
push dword injectsize
call printf
pop ecx
pop ecx
; get NEW brk
mov ebx, [ptr] ; dynamic alloc of $skip-$inject bytes
add ebx, $skip-$inject
mov eax, 45 ; 45 = linux brk system call
int 0x80 ; syscall software interrupt
mov [ptr2], eax ; store new brk in ptr2
push eax
push dword ptrval
call printf
pop ecx
pop ecx
mov ebx, 0 ; loop counter
push skip ; address used by injected ret instruction
whilecp:
CMP ebx, ($skip-$inject)/4 ; div 4 since we move 4 bytes at once (32 bits reg)
JZ copyok
copy: ; perform the instruction copies
mov eax, [inject+ebx*4]
mov [ptr+ebx*4], eax
mov eax, [inject+ebx*4]
push eax
push dword dump
call printf
pop ecx
pop ecx
add ebx, 1 ; inc loop counter
JMP whilecp
copyok:
JMP ptr ; jump to heap code
JMP skip
inject:
; THIS METHOD WORKS
;mov edx, injectionlen
;mov ecx, injection
;mov ebx, 1 ; fd = 1 = stdout
;mov eax, 4 ; 4 = linux write system call
;int 0x80 ; syscall software interrupt
;nop
; THIS METHOD DOES NOT WORK
push dword injection
call printf
pop ecx
ret
nop
nop
nop
nop
skip:
push dword backloop
call printf
pop ecx
popa
mov eax, 0
leave
ret