"The value of ESP was not properly saved across a function call." even with LEAVE - visual-c++

When attempting to call a method which is defined in assembly, I'm receiving the error "The value of ESP was not properly saved across a function call.", using Visual Studio 2012. Looking at other questions, a common factor was the mention that the assembly may not have the LEAVE instruction at the end of each label.
I am receiving this error, but with the following code, which does include the LEAVE instruction.
section .bss
vs: resb 13 ; 12-byte vendor string + NULL char
ns: resb 49 ; 48-byte proc. name + NULL char
section .text
global _meta_vendor
global _meta_procname
_meta_vendor:
push ebp
mov ebp, esp
mov eax, 0h
cpuid
mov [vs], ebx
mov [vs + 4], edx
mov [vs + 8], ecx
mov byte [vs + 12], 0h
mov eax, vs
leave
ret
_meta_procname:
push ebp
mov ebp, esp
mov eax, 80000002h
cpuid
mov [ns], eax
mov [ns + 4], ebx
mov [ns + 8], ecx
mov [ns + 12], edx
mov eax, 80000003h
cpuid
mov [ns + 16], eax
mov [ns + 20], ebx
mov [ns + 24], ecx
mov [ns + 28], edx
mov eax, 80000004h
cpuid
mov [ns + 32], eax
mov [ns + 36], ebx
mov [ns + 40], ecx
mov [ns + 44], edx
mov byte [ns + 48], 0h
mov eax, ns
leave
ret
Function prototypes for those labels are then in a header file which contains only this:
#include <cstdint>
extern "C" {
char* meta_vendor();
char* meta_procname();
}
Any insight as to why I am receiving this error?
Note that, if I click "Continue" on the popup which appears, the expected values do appear.

The problem was solved by adding push ebx and pop ebx as is shown below:
_meta_vendor:
push ebp
mov ebp, esp
push ebx
; code...
pop ebx
leave
ret

Related

MASM32 - set a string value on a single line, esi not correctly set, access violation

I am trying to use rep movsb to set a string to a variable. The rep movsb throws an access violation because my mov esi, offset ‘Dog’ is not pointing to the correct memory address. I am including the code and the only thing I can think of is that it might have something to do with the segments. I have a paid attention to the segment registers in the debugger, but I am afraid I do know exactly how to work the problem if the problem is in fact segment registers. Other than that I don’t know, I just know that esi is not being set correctly, but am unsure why.
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
readArray PROTO
stringLength PROTO : ptr dword
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
array dword 512 dup(?) ; pointer in memory to start of array
; newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
LOCAL DbRecord02:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
;mov byte ptr [DbRecord01.WordOne], 'D'
;mov byte ptr [DbRecord01.WordOne + 1], 'o'
;mov byte ptr [DbRecord01.WordOne + 2], 'g'
;mov byte ptr [DbRecord01.WordOne + 3], 0
lea edi, DbRecord01.WordOne
mov esi, offset 'Dog' ; esi is not set correctly, inspection of memory does not show 'Dog'
mov ecx, 3
rep movsb
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
mov [DbRecord02.Id], 2;
; any other way than one character at a time?
mov byte ptr [DbRecord02.WordOne], 'C'
mov byte ptr [DbRecord02.WordOne + 1], 'a'
mov byte ptr [DbRecord02.WordOne + 2], 'r'
mov byte ptr [DbRecord02.WordOne + 3], 0
mov byte ptr [DbRecord02.WordTwo], 'H'
mov byte ptr [DbRecord02.WordTwo + 1], 'o'
mov byte ptr [DbRecord02.WordTwo + 2], 'u'
mov byte ptr [DbRecord02.WordTwo + 3], 's'
mov byte ptr [DbRecord02.WordTwo + 4], 'e'
mov byte ptr [DbRecord02.WordTwo + 5], 0
mov byte ptr [DbRecord02.WordThree], 'W'
mov byte ptr [DbRecord02.WordThree + 1], 'i'
mov byte ptr [DbRecord02.WordThree + 2], 'n'
mov byte ptr [DbRecord02.WordThree + 3], 'd'
mov byte ptr [DbRecord02.WordThree + 4], 'o'
mov byte ptr [DbRecord02.WordThree + 5], 'w'
mov byte ptr [DbRecord02.WordThree + 6], 's'
mov byte ptr [DbRecord02.WordThree + 7], 0
mov [DbRecord02.Year], 2002;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
invoke addElement, addr DbRecord02
invoke readArray
invoke ExitProcess, 0
ret
main endp
addElement proc uses edx DbRecordPointer: ptr DbRecord
Local newElementPointer: Dword
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE
mov newElementPointer, eax
invoke RtlMoveMemory, eax , DbRecordPointer, sizeof DbRecord
mov edx, arrayCount
mov dword ptr [array +4*edx], eax
inc edx
mov arrayCount, edx
ret
addElement endp
readArray proc uses ebx
xor ebx, ebx
.while ebx < arrayCount
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordOne]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordOne]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordTwo]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordTwo]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordThree]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordThree]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
inc ebx
.endw
ret
readArray endp
stringLength proc uses ecx stringPtr: ptr dword
; find length of string
mov edi, stringPtr
mov ecx, -1
mov al, 0
repne scasb
not ecx
mov eax, ecx
ret
stringLength endp
end main

Learning assembly. how to make code faster

I started to learn assembly some days ago and i write my first ever piece of code using user input, string functions, passing arguments by stack or by register etc...
I have some questions. Do you have some advices to make my code faster. For example, in my atoi function, i know that imul is time consuming. Maybe, there are enormous mistakes but as far as i know, many things to improve for sure. So my main question is : are there fatal errors in this first code and my second is : any type to refactoring code with faster instructions
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
%macro printm 2
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
%macro prolog 0
push ebp,
mov ebp, esp
%endmacro
%macro epilog 0
mov esp, ebp
pop ebp
%endmacro
section .text
global _start
_start:
; first check if our strlen proc works
push dword msgbegin
call strlen
add esp, byte 4
cmp eax, lenbegin
je .suite ; it works, we continue
; exiting prog if the len computed in rax != lenbegin
mov eax, 1
int 0x80
.suite:
; check if strcpy works printing res (msgbegin -> srcdst)
push dword lenbegin
push dword msgbegin
push dword strdst
call strcpy
add esp, byte 12
push dword lenbegin
push dword strdst
call print
add esp, byte 8
; first input
printm msgbinp1, leninp1
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
printm msgbinp2, leninp2
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
printm msgbinp3, leninp3
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, bignum
mov edx, 4
int 0x80
mov edx, bignum
call atoi
cmp eax, 123
je .success ; exit if bignum != 123
mov eax, 1
int 0x80
.success:
; need to strip line feed from bignum
printm bignum, 4
printm msgoutp, lenoutp
; now we compute the sum
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
printm msgres, lenres
; we print it
printm sum, 1
; exiting the programm
mov eax, 1
int 0x80
print:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, [ebp + 8]
mov edx, [ebp + 12]
int 0x80
mov esp, ebp
pop ebp
ret
strcpy:
push ebp
mov ebp, esp
mov ecx, [ebp + 16]
mov esi, [ebp + 12]
mov edi, [ebp + 8]
rep movsb
mov esp, ebp
pop ebp
ret
strlen:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp + 8]
sub ecx, ecx
sub al, al
not ecx
cld
repne scasb
not ecx
lea eax, [ecx] ; keep null term in size
pop ecx
pop edi
mov esp, ebp
pop ebp
ret
atoi:
xor eax, eax ; zero a "result so far"
.top:
movzx ecx, byte [edx] ; get a character
inc edx ; ready for next one
cmp ecx, '0' ; valid?
jb .done
cmp ecx, '9'
ja .done
sub ecx, '0' ; "convert" character to number
imul eax, 10 ; multiply "result so far" by ten
add eax, ecx ; add in current digit
jmp .top ; until done
.done:
ret
section .data
msgbegin db "hello everyone !", 0xa, 0
lenbegin equ $ - msgbegin
msgbinp1 db "Enter a digit : ", 0xa, 0
leninp1 equ $ - msgbinp1
msgbinp2 db "Enter second digit : ", 0xa, 0
leninp2 equ $ - msgbinp2
msgbinp3 db "Enter third digit : ", 0xa, 0
leninp3 equ $ - msgbinp3
msgoutp db "is equal to 123 !", 0xa, 0
lenoutp equ $ - msgoutp
msgres db "sum of x and y is ", 0xa, 0
lenres equ $ - msgres
strdst times lenbegin db 0
segment .bss
sum resb 1
num1 resb 2
num2 resb 2
bignum resd 4
Thanks you. I started reading the doc but i'm not sure that i understood key concepts.

How to find characters in a string Assembly x86?

I'm trying to rewrite the C code below in Assembly x86
int myFn( char * v, char c, int size ) {
int i;
for(i=0; i < size; i++ )
if( v[i] == c )
return i;
return -1;
}
I've tried to use this code in x86:
myFn:
mov esi, 0
mov ebx, [esp + 8]
mov ecx, [esp + 12]
FOR:
mov eax, -1
cmp esi, [esp + 4]
jge ENDFOR
cmp [ecx + esi], ebx
je EQUAL
inc esi
jmp FOR
EQUAL:
mov eax, [esi]
ENDFOR:
ret
I've also created this program to test the function:
section .data
fmt: db "strfind: %d", 10, 0
str: db "test", 0
section .text
global main
extern printf
main:
mov eax, 's'
mov ebx, 4
push str
push eax
push ebx
call myFn
add esp, 12
push eax
push fmt
call printf
add esp, 8
ret
myFn:
mov esi, 0
mov ebx, [esp + 8]
mov ecx, [esp + 12]
FOR:
mov eax, -1
cmp esi, [esp + 4]
jge ENDFOR
cmp [ecx + esi], ebx
je EQUAL
inc esi
jmp FOR
EQUAL:
mov eax, [esi]
ENDFOR:
ret
I'm getting Segmentation Fault error or the wrong result when trying to test it. I believe the problem is when comparing the character of the string with the character I want to find

Converting generated shellcode to hexademical

I have written the following shellcode, which spawns a shell.
global _start
_start:
jmp short GotoCall
shellcode:
pop esi
xor eax, eax
mov byte [esi+7], al
lea ebx, [esi]
mov long [esi + 8], ebx
mov long [esi + 12], eax
mov byte al, 0x0b
mov ebx, esi
lea ecx, [esi + 8]
lea edx, [esi + 12]
int 0x80
GotoCall:
call shellcode
db '/bin/shJAAAAKKKK'
I assembled the instructions with nasm and linked it with ld.
I want the assembly instructions to be represented in hexadecimal so that they can be written in the following C code where the variable shellcode contains the above assembly instructions in hexademical. However, doing this manually would be tedious and I want to know if there is a fast way to do this.
char shellcode[] = "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46"
"\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
"\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}

Swapping first and last characters of string results in seg fault

My goal is to swap the first character with the last character of the string some_str in x86-assembly.
Here is my attempt:
; assemble and link with:
; nasm -f elf32 -g test.asm && ld -melf_i386 test.asm.o -o test
section .text
global _start
extern printf
_start:
mov eax, some_str
_loop:
mov di, [eax + 4] ; ptr to end char
mov si, [eax] ; ptr to start char
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
mov [si], dl ; start char = end char
mov [di], al ; end char = char 1
mov edx, len
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80
ret
mov eax, 1
int 0x80
section .data
some_str db `abcd`, 0xa
len equ $ - some_str
For some reason I am oblivious to the lines:
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
Causes the program to result in a segmentation fault.
The expected stdout is:
dbca
Actual stdout:
Segmentation fault (core dumped)`
Is there something I am missing? How do I correct this code to correctly swap the first and last character of some_str.
Your code seems to be doing something much more complicated than necessary. After mov eax, some_str, we have that eax points to one of the bytes that wants to be swapped, and eax+4 points to the other. So just load them into two 8-bit registers and then store them back the other way around.
mov eax, some_str
mov cl, [eax]
mov dl, [eax + 4]
mov [eax + 4], cl
mov [eax], dl
And you're done and can proceed to write out the result.
Note it isn't necessary to load the pointer into eax first; you could also do
mov cl, [some_str]
mov dl, [some_str + 4]
mov [some_str + 4], cl
mov [some_str], dl
If you really wanted to have two different registers to point to the two different bytes: first of all, they need to be 32-bit registers. Trying to address memory in 32-bit mode using 16-bit registers si, di is practically never going to work. Second, mov edi, [eax] would load edi with the contents of the memory at location eax, which is some bytes of your string, not a pointer. You'd want simply mov edi, eax. For the second one, you can use lea to do the arithmetic of an effective address calculation but keep the resulting pointer instead of doing a load. So I think the way to turn your code into something in the original (inefficient) spirit, but correct, would be
mov edi, eax
lea esi, [eax+4]
mov dl, [edi]
mov al, [esi]
mov [esi], dl
mov [edi], al

Resources