flat assembler
Message board for the users of flat assembler.

Index > Linux > write zero term. string located in stack space

Author
Thread Post new topic Reply to topic
fly



Joined: 27 Apr 2005
Posts: 11
Location: Salzburg, Austria
fly 27 Apr 2005, 09:01
Hello!
I'm a newbie in assembler coding, so please excuse me if this question is stupid. I've created a litte prog from several examples found in this board. There is i simple macro that write a zero terminated string to the console. This works fine if the string is located in the memory (gfp in code) area defined at the beginning of the prog, but fails if the memory allocated by the stack (rbp in code) is used.
Is there an error in the Write macro, or is it even possible to use the rbp pointer by a system call?
I had already wasted a lot of time for solving this problem, so i would be pleased if anyone can help me.

regards,
fly

Code:
format ELF64 executable

;macros

_MAX64 = 0FFFFFFFFFFFFFFFFh
sys_write = 0x4
stdout = 0x1
sys_exit = 0x1

macro SysExit ExitCode
{
        mov ebx, ExitCode
        mov eax, sys_exit 
        int 0x80
}

macro Write ;write zero terminated string pointed to by rax
{
        ;get string length
        push rbx
        push rcx
        push rax
        push rdi

        mov rdi, rax
        mov rcx, _MAX64
  xor rax, rax  ;zeroing rax
        cld             ;clear direction flag (DF), registers are now incremented
        repnz ;repeat next instruction while z is set, or at most rcx times
        scasb ;compare rax with byte pointed to by rdi

        mov rax, (_MAX64 - 1)
        sub rax, rcx
        mov rdx, rax    ;copy result to rdx (for use by system call)

        pop rdi
        pop rcx         ;set pointer to string

        ;invoke system call
        mov     rax,sys_write
        mov     rbx,stdout
        int     0x80

        pop rcx ;restore registers
        pop rbx
}

;global variables
section readable writeable

strCRLF db 13, 10, 0

;reserve some bytes for simulated stack spacs
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
gfp db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

;main

section readable executable
entry $
enter 2, 0

mov byte [rbp], 0
mov byte [rbp-1], 0
mov byte [rbp-2], 0
mov byte [rbp-3], 0
mov byte [rbp-4], 65
mov byte [rbp-5], 0
mov byte [rbp-6], 0
mov byte [rbp-7], 0

mov byte [gfp], 0
mov byte [gfp-1], 0
mov byte [gfp-2], 0
mov byte [gfp-3], 0
mov byte [gfp-4], 65
mov byte [gfp-5], 0
mov byte [gfp-6], 0
mov byte [gfp-7], 0

mov rax, strCRLF
Write

mov rax, rbp
dec rax
dec rax
dec rax
dec rax
Write

mov rax, strCRLF
Write


mov rax, gfp
dec rax
dec rax
dec rax
dec rax
Write

mov rax, strCRLF
Write


SysExit 0

leave    
Post 27 Apr 2005, 09:01
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20409
Location: In your JS exploiting you and your system
revolution 27 Apr 2005, 09:45
I am not familiar with Linux but I will try to help if I can.

try this:

Code:
enter 8,0
    


instead of:

Code:
enter 2,0
    
Post 27 Apr 2005, 09:45
View user's profile Send private message Visit poster's website Reply with quote
fly



Joined: 27 Apr 2005
Posts: 11
Location: Salzburg, Austria
fly 27 Apr 2005, 10:12
thx! unfortunately this doesn't affect the output of the prog. i've tried different values for this parameter. also i have verified the memory location at [rbp]-[rbp-7], the bytes are written correctly into it.
Post 27 Apr 2005, 10:12
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20409
Location: In your JS exploiting you and your system
revolution 28 Apr 2005, 01:51
The only other thing I can think of is if SS:base <> DS:base. Does Linux use the same base address for both segment selectors?
Post 28 Apr 2005, 01:51
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 28 Apr 2005, 06:50
In long mode it's impossible for them to have different bases.
Post 28 Apr 2005, 06:50
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 28 Apr 2005, 11:38
if it wouldn't, you would have to use FAR pointers for stack variables, and thus all external pointers (about which you don't know if they point to stack or to data) would have to be FAR, so this way you could forget about coding in C-likes Smile
Post 28 Apr 2005, 11:38
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 28 Apr 2005, 11:44
by using Write you destroy (with push's) data on the stack you've just put on it with those mov [ebp+xxx] statements. After mov's you have to update esp
Code:
 sub esp, length_of_my_data_on_the_stack    
as well. And at the and of your program you have to apply an
Code:
 add esp, length_of_my_data_on_the_stack    
in order to set the stack pointer back.
Post 28 Apr 2005, 11:44
View user's profile Send private message Reply with quote
fly



Joined: 27 Apr 2005
Posts: 11
Location: Salzburg, Austria
fly 28 Apr 2005, 12:19
i use the "enter 8, 0" instruction, therefore the stack pointer should be set rigth (is that correct?)
as privalov mentioned it, the 64bit mode uses flat memory model (non-segmented), and all segment-base adresses have a value of 0 (->amd64 prog manual pg32). so that also cannot be the reason.
now i'm try to follow vid's proposal and write a mallac/dealloc routine and store only pointers to my local variables on the stack
Post 28 Apr 2005, 12:19
View user's profile Send private message Reply with quote
Endre



Joined: 29 Dec 2003
Posts: 215
Location: Budapest, Hungary
Endre 28 Apr 2005, 18:07
fly wrote:
i use the "enter 8, 0" instruction, therefore the stack pointer should be set rigth (is that correct?)
Sorry, you are right. I converted your code by simply changing the 64 bit registers to 32 ones and wrote enter 4,0 instead of enter 2,0 and I got the correct result:

A
A

Even it didn't count either that your 'leave' will never be executed.

What if you write merely ELF instead of ELF64 after the format directive? It might be that you need a 64 bit kernel for running ELF64 but you just have a 32 bit one.
Post 28 Apr 2005, 18:07
View user's profile Send private message Reply with quote
fly



Joined: 27 Apr 2005
Posts: 11
Location: Salzburg, Austria
fly 28 Apr 2005, 20:35
thanks for the hint with the leave instruction!
i hadn't minded the possibility to try the code in 32bit mode, and i'm wonder about - it works fine. i had changed the code as you described it (find/replace r**->e** and use ELF instead of ELF64).
the 32bit executable emit:
A
A

but the 64bit executable emit:
A

now i'm completely perplexed Confused

running elf64 executables should be no problem (amd64 athlon with mandrake 10.1 64bit distro)
i attached the two files, perhaps anyone with a 64bit system want to try it...


Description: write32.asm
write64.asm

Download
Filename: write.tgz
Filesize: 973 Bytes
Downloaded: 773 Time(s)

Post 28 Apr 2005, 20:35
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.