This question already has answers here:
what is the difference between byte and dword in assembly and how to use them [duplicate]
(1 answer)
How to load a single byte from address in assembly
(1 answer)
Closed 3 months ago.
I am trying to implement a function in x86 nasm assembler which removes every n-th character from string. However, I am experiencing quite unexpected behaviour and don't really understand why it doesn't work.
// main.c
#include <stdio.h>
char *rem(char *s, int n);
int main(int argc, char *argv[])
{
char s[] = "abcabcabc";
int n = 3;
printf("%s\n", rem(s, n));
}
; rem.s
section .text
global rem
rem:
push ebp
mov ebp, esp
push esi
push edi
push ebx
mov eax, [ebp+8] ; read pointer
mov ecx, [ebp+8] ; write pointer
mov edx, [ebp+12] ; n
mov esi, 1 ; counter
loop:
cmp BYTE [eax], 0
jz fin
cmp edx, esi
jz remove
dont_remove:
; move current character to position
; pointed by the write pointer
mov edi, [eax]
mov [ecx], edi
inc ecx ; increase write pointer
inc eax ; increase read pointer
inc esi ; counter++
jmp loop
remove:
mov esi, 1 ; reset the counter
inc eax ; increase only read pointer
jmp loop
fin:
mov edi, [eax]
mov [ecx], edi
mov eax, [ebp+8]
pop ebx
pop edi
pop esi
pop ebp
ret
# Makefile
EXEFILE = main
OBJECTS = main.o rem.o
CCFMT = -m32
NASMFMT = -f elf32
CCOPT = -m32 -c
NASMOPT = -w+all
.c.o:
cc -g $(CCFMT) $(CCOPT) $<
.s.o:
nasm $(NASMFMT) $(NASMOPT) $<
$(EXEFILE): $(OBJECTS)
cc $(CCFMT) -o $(EXEFILE) $(OBJECTS)
clean:
rm *.o $(EXEFILE)
After running the code with command make && ./main I expected to see ababab (so that it removes all of the c's from "abcabcabc", in other way, removes every 3rd character). However it returns abacb. What is causing this issue? Thanks in advance for help
Related
C code
#include <stdio.h>
int fibonacci(int);
int main()
{
int x = fibonacci(3);
printf("Fibonacci is : %d",x);
return 0;
}
Assembly
section .text
global fibonacci
fibonacci:
push ebp;
mov ebp, esp;
; initialize
mov dword [prev], 0x00000000;
mov dword [cur], 0x00000001;
mov byte [it], 0x01;
mov eax, dword [ebp + 8]; // n = 3
mov byte [n], al;
getfib:
xor edx,edx;
mov dl, byte [n];
cmp byte [it] , dl;
jg loopend;
mov eax,dword [prev];
add eax, dword [cur];
mov ebx, dword [cur];
mov dword [prev], ebx;
mov dword [cur] , eax;
inc byte [it];
jmp getfib;
loopend:
mov eax, dword [cur];
pop ebp;
ret;
section .bss
it resb 1
prev resd 1
cur resd 1
n resb 1
I was trying to run this assembly function in C code and on debugging , i saw that value in variable x in C code is right but there is some error coming when i use the printf function
Need Help on it
Command to compile:
nasm -f elf32 asmcode.asm -o a.o
gcc -ggdb -no-pie -m32 a.o ccode.c -o a.out
Click Below Pictures if they seem blurred
Below is debug before printf execute
Below is after printf execute
Your code does not preserve the ebx register which is a callee-preserved register. The main function apparently tries to do some rip-relative addressing to obtain the address of the format string for printf using ebx as a base register. This fails because your code overwrote ebx.
To fix this issue, make sure to save all callee-saved registers before you use them and then restore their value on return. For example, you can do
fibonacci:
push ebp
mov ebp, esp
push ebx ; <---
...
pop ebx ; <---
pop ebp
ret
I am writing an assembly program and a C program; the C program will call a function written in assembly. The environment is Ubuntu 18.04LTS x64.
It is designed for 32 bits x86 and will be compiled by NASM, but it can't pass correct parameters.
To simplify the problem, I just changed my function to get the sum of a and b.
extern int FindPattern(int a,int b);
int result;
result=FindPattern(1,1);
printf("%d\n",result);
global FindPattern
section .text
FindPattern:
push ebp
push esi
push edi
push ebx
push edx
push ecx
mov ebp,esp
mov esi,[ebp+8] ; a
mov edi,[ebp+12] ; b
mov eax,0
add eax,esi
add eax,edi ; return a+b
pop ecx
pop edx
pop ebx
pop edi
pop esi
pop ebp
ret
The function just adds a and b, and returns the sum. The sum should be 2, however I got a random number like 1449041840. It seems the assembly didn't get correct parameters.
What's wrong with the code and how can I fix it?
# Makefile
cc=gcc
ASMBIN=nasm
all : asm cc link
asm:
$(ASMBIN) -o findpattern.o -f elf32 -l findpattern.lst findpattern.asm
cc :
$(cc) -m32 -c -g -O0 -fpack-struct graph_io.c
link :
$(cc) -m32 -o graph_io findpattern.o graph_io.o
clean:
rm *.o
rm graph_io
rm findpattern.lst
Your stack frame set up is wrong. push ebp; mov ebp, esp must be issued before any other stack movement takes place.
By pushing other stuff on the stack before setting up ebp you have set up ebp to point to a different place than usual, causing all the offsets to be different. To fix this, first set up the stack frame, then push the remaining registers:
global FindPattern
section .text
FindPattern:
push ebp
mov ebp,esp
push esi
push edi
push ebx
push edx
push ecx
mov esi,[ebp+8] ; a
mov edi,[ebp+12] ; b
mov eax,0
add eax,esi
add eax,edi ; return a+b
pop ecx
pop edx
pop ebx
pop edi
pop esi
pop ebp
ret
I'm trying to write a simple shellcode to read the content of a file.
Here is my assembly:
xor eax, eax
xor ecx, ecx
xor edx, edx
push 0x73 ; /home/users/level05/.pass
push 0x7361702e ;
push 0x2f35306c
push 0x6576656c
push 0x2f737265
push 0x73752f65
push 0x6d6f682f
mov ebx, esp
mov al, 0x05
int 0x80 ; open
mov ebx, eax
xor eax, eax
xor edx, edx
mov dl, 0x10
mov ecx, esp
mov al, 0x03
int 0x80 ; read
mov ecx, eax
xor ebx, ebx
mov bl, 0x01
mov al, 0x04
int 0x80 ; write
`
So if I transform it into shellcode, and simply run it, I have a segmentation fault.
I verified my code and it seems good. The file to read exists too, and I have the rights on it.
I compile it to be ran on x86 linux.
Im compiling the program with : this main:
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"MYSHELLCODE";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
And I run : gcc c-shell.c -o shell -fno-stack-protector -z execstack -m32
The shellcode : \x31\xc0\x31\xc9\x31\xd2\x6a\x73\x68\x2e\x70\x61\x73\x68\x6c\x30\x35\x2f\x68\x6c\x65\x76\x65\x68\x65\x72\x73\x2f\x68\x65\x2f\x75\x73\x68\x2f\x68\x6f\x6d\x89\xe3\xb0\x05\xcd\x80\x89\xc3\x31\xc0\x31\xd2\xb2\x10\x89\xe1\xb0\x03\xcd\x80\x89\xc1\x31\xdb\xb3\x01\xb0\x04\xcd\x80
68 byte
`
I'm looking to call malloc() from an ASM file.
In ASM:
extern malloc
didn't work. I would like to link the CStdLib.
What exactly does "didn't work" mean? You need to do more than just use extern, you need to link against the C Library. The easiest way is to use gcc to link. As you didn't mention if your code is 32 bit or 64, I will go with 32 bit. The process is basically the same for 64 bit.
extern exit, printf, malloc, free
global main
BUFFER_SIZE equ 27
section .data
fmtstr db "%s", 10, 0
section .text
main:
push BUFFER_SIZE
call malloc
add esp, 4 * 1
mov esi, eax
xor ecx, ecx
mov edx, 97
.FillBuffer:
mov byte [esi + ecx], dl
inc edx
inc ecx
cmp ecx, BUFFER_SIZE - 1
jne .FillBuffer
mov byte [esi + ecx], 0
push esi
push fmtstr
call printf
add esp, 4 * 2
push esi
call free
add esp, 4 * 1
push 0
call exit
add esp, 4 * 1
and the makefile:
APP=malloctest
all: $(APP) clean
$(APP): $(APP).o
gcc -o $(APP) $(APP).o
$(APP).o: $(APP).asm
nasm -f elf $(APP).asm
clean:
rm $(APP).o
I need to get my char pointer and after that i print it on the screen to see if it works ok.
I read the text from a file and put in my char pointer (sizeof(char*) + filesize) + 1.. in the end i put the '\0'.
If i printf my char* its fine
Here is my asm code
; void processdata(char* filecontent);
section .text
global processdata
extern printf
section .data
FORMAT: db '%c', 10, 0 ; to break the line 10, 0
processdata:
push ebp
mov ebp, esp
mov ebx, [ebp]
push ebx
push FORMAT
call printf
add esp, 8
when i run it i just see trash in my variable.
As violet said:
; void processdata(char* filecontent);
section .text
[GLOBAL processdata] ;global processdata
extern printf
section .data
FORMAT: db '%c', 0
EQUAL: db "is equal", 10, 0
processdata:
lea esi, [esp]
mov ebx, FORMAT
oook:
mov eax, [esi]
push eax
push ebx
call printf
inc esi
cmp esi, 0x0
jnz oook
Thanks
quote demonofnight
But if i need to increment, can i do that?
Using your original function arg of char* and your %c format, something like this:
lea esi, [esp+4]
mov ebx, FORMAT
oook:
mov eax, [esi]
push eax
push ebx
call printf
inc esi
cmp [esi], 0x0
jnz oook
[edit: ok sry, i hacked that quickly into some shenzi winOS inline __asm block]
here's a complete thing done in linux and nasm:
; ----------------------------------------------------------------------------
; blah.asm
; ----------------------------------------------------------------------------
extern printf
SECTION .data ;local variables
fmt: db "next char:%c", 10, 0 ;printf format, "\n",'0'
SECTION .text ;hack in some codes XD
global foo
foo: ;foo entry
push ebp ;set up stack frame
mov ebp,esp
mov esi, [ebp+8] ;load the input char array to the source index
oook: ;loop while we have some chars
push dword [esi] ;push next char addy in string to stack
push dword fmt ;push stored format string to stack
call printf
add esp, 8 ;restore stack pointer
inc esi ;iterate to next char
cmp byte [esi], 0 ;test for null terminator byte
jnz oook
mov esp, ebp ;restore stack frame
pop ebp
mov eax,0 ;return 0
ret ;done
blah.c (that invokes the .asm foo) :
/*-----------------------------------------------
blah.c
invokes some asm foo
------------------------------------------------*/
#include <stdio.h>
void foo(char*);
int main() {
char sz[]={"oook\n"};
foo(sz);
return 0;
}
&here's the commandline stuff:
$ nasm -f elf blah.asm -o blah.o
$ gcc -o blah blah.c blah.o
$ ./blah
next char:o
next char:o
next char:o
next char:k
next char:
$
$ nasm -v
NASM version 2.09.08 compiled on Apr 30 2011
$ uname -a
Linux violet-313 3.0.0-17-generic #30-Ubuntu SMP Thu Mar 8 17:34:21 UTC 2012 i686 i686 i386 GNU/Linux
Hope it works for you ;)
On linux x86 the first function parameter is in ecx. The printf format for printing a pointer is "%p".
So something along
...
FORMAT: db '%p', 10, 0 ; to break the line 10, 0
processdata:
mov eax, [esp+4]
push eax
push format
call printf
add esp, 8
ret
should work, assuming the rest of your code is correct and your are using gcc's calling convention.
This is assuming that the pointer you want to print is on the stack.
The reason for the crash is probably that you push 12 bytes on the stack, but correct the stack pointer by only 8.