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