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

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

Related

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

Intel x86 (IA32) assembly decoder stub for custom encoder not working as expected

I have written a custom encoder which encodes my shellcode in this way:
First it reverses(swaps) all adjacent bytes in the original shellcode, and then it XORs each byte with value "0xaa" - I did all sanity check to ensure my original shellcode doesn't have this value, which might break my shellcode (by causing bad characters as a result of the encode). Output of my encoder:
Original Shellcode( 25 Bytes) :
0x31,0xc0,0x50,0x68,0x2f,0x2f,0x6c,0x73,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0x50,0x89,0xe2,0x53,0x89,0xe1,0xb0,0xb,0xcd,0x80,
Step1(Reverse adjacent Bytes)-Encoded Shellcode( 25 Bytes) :
0xc0,0x31,0x68,0x50,0x2f,0x2f,0x73,0x6c,0x2f,0x68,0x69,0x62,0x89,0x6e,0x50,0xe3,0xe2,0x89,0x89,0x53,0xb0,0xe1,0xcd,0xb,0x80,
Step2(XOR-each-BYTE-with-0xaa)-Encoded Shellcode( 25 Bytes) :
0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,
My original shellcode's purpose: it just executes /bin/ls on Linux systems using the "execve" syscall. Full code:
global _start
section .text
_start:
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push eax
mov edx, esp
push ebx
mov ecx, esp
mov al, 11
int 0x80
In order to execute the shellcode I'm practicing how to write a decoder stub, which will decode my custom encoded shellcode, and then execute it on a target machine.
This is my decoder stub assembly code:
global _start
section .text
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov cl, 12
jmp short call_decoder
; first : decode by XOR again with same value 0xaa
decode1:
pop esi
xor byte [esi], 0xaa
jz decode2
inc esi
jmp short decode1
; second: rearrange the reversed adjacent BYTES, as part of encoding
decode2:
pop esi
mov bl, byte [esi + eax]
mov dl, byte [esi + eax + 1]
xchg bl, dl
mov byte [esi + eax], bl
mov byte [esi + eax + 1], dl
add al, 2
loop decode2
; execute Shellcode
jmp short Shellcode
call_decoder:
call decode1
; an extra byte 0xaa added at the end of encoded shellcode, as a marker to end of shellcode bytes.
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,0xaa
But above code gives me a segment fault. I'm unable to find a failure point on gdb debugger. Need some help on what I'm doing wrong.
Based on comments made by #prl, these are the changes I did in my decoder stub, and now it works as expected:
global _start
section .text
; initialize registers
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov cl, 12
jmp short call_decoder
; set starting address of Shellcode in esi register
decoder:
pop esi
mov edi, esi
; first: decode by XOR again with same value 0xaa
decode1:
xor byte [edi], 0xaa
jz decode2
inc edi
jmp short decode1
; second: rearrange the reversed adjacent BYTES, as part of encoding
decode2:
mov bl, byte [esi + eax]
mov dl, byte [esi + eax + 1]
xchg bl, dl
mov byte [esi + eax], bl
mov byte [esi + eax + 1], dl
add al, 2
loop decode2
jmp short Shellcode
call_decoder:
call decoder
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,0xaa
EDIT2 :
A much concise and a better looking code - also no need to hardcode the length of Shellcode:
global _start
section .text
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
jmp short call_decoder
decoder:
pop esi
mov cl, codeLen
dec cl
decode:
cmp al, cl
jz last_byte_odd
xor byte [esi + eax], 0xaa
mov bl, byte [esi + eax]
xor byte [esi + eax + 1], 0xaa
xchg byte [esi + eax + 1], bl
mov byte [esi + eax], bl
add al, 1
cmp al, cl
jz Shellcode
add al, 1
jmp short decode
last_byte_odd:
xor byte [esi + eax], 0xaa
jmp short Shellcode
call_decoder:
call decoder
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a
codeLen equ $-Shellcode
I leave it up to the low level and shell-coding enthusiasts, to decipher the logic.

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

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

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

Resources