From a tutorial I got that movsb will copy data from ds:si to es:di. But in my case it's not working.
While try to debugging with gdb i cannot able to print values in s1 and s2 which decleared in .data section and .bss section respectively.
Any one please help how we can see value of s2 ,while printing $p2 i got void in debugging?
Why the value of s2 don't change with that of s1 here ?
code is given below
section .text
global _start
_start:
mov esi,s1
mov edi,s2
cld
rep movsb
mov edx,20
mov ecx,s2
mov ebx,1
mov eax,4
int 80h
mov eax,1
int 80h
section .data
s1 db 'qwerty',0
section .bss
s2 resb 20
When Linux starts your process, all your registers (including ECX) will be zero, except for ESP. (The ABI says they can hold garbage, but Linux chooses zero to avoid info leaks.)
Thus rep movsb will copy zero bytes. It's memcpy, not strcpy, it doesn't look at the data.
This is why your program doesn't just crash, like you'd expect from using rep movsb without setting ECX first.
Related
Starting to learn NASM assembly, I was looking at some assembly questions here in Stack Overflow and found this one here:
Concatenating strings from registers and printing them
I believe that this question is not duplicated because I am trying to
replicate the code in NASM and also things were not very clear in the
other question.
I decided to replicate this code in NASM, but I did not quite understand the MASM code in question.
I learned about CPUID and did some testing programs.
In order, I'd like to know how we can concatenate registers and then print them on the screen USING NASM.
I want to print 'ebx' + 'edx' + 'ecx' because this is how the CPUID output is organized by what I see in GDB.
I called CPUID with eax=1
"String" is not a very precise term. The Vendor Identification String of CPUID/EAX=0 contains only 12 ASCII characters, packed into 3 DWORD registers. There is no termination character like in C nor a length information like in PASCAL. But it's always the same registers and it's always 3*4=12 bytes. This is ideal for the write-syscall:
section .bss
buff resb 12
section .text
global _start
_start:
mov eax, 0
cpuid
mov dword [buff+0], ebx ; Fill the first four bytes
mov dword [buff+4], edx ; Fill the second four bytes
mov dword [buff+8], ecx ; Fill the third four bytes
mov eax, 4 ; SYSCALL write
mov ebx, 1 ; File descriptor = STDOUT
mov ecx, buff ; Pointer to ASCII string
mov edx, 12 ; Count of bytes to send
int 0x80 ; Call Linux kernel
mov eax, 1 ; SYSCALL exit
mov ebx, 0 ; Exit Code
int 80h ; Call Linux kernel
I am using a x86 assembly to make a simple program that compares two words and prints out if they are equal (i know its usless im just learning and testing out things) its working properly but right after the answer i get printed out with alot of garbage and i dont understand what is causing this bug
SECTION .bss
SECTION .text
SECTION .data
HelloMsg: db "Helllo",10
HelloLength: equ $-HelloMsg
HellloMsg: db "Helllo",10
HellloLength: equ $-HellloMsg
One: db "First",10
OneLen: equ $-One
Two: db "Second",10
TwoLen: equ $-Two
global _start
_start:
nop
mov eax,4
mov ebx,1
mov ecx,HellloLength
mov edx,HelloLength
cmp ecx,edx
je true
mov ecx,One
mov edx,OneLen
int 80H
true:
mov ecx,Two
mov edx,One
int 80H
MOV eax,1
mov ebx,0
int 80H
Output :
Sorry if im asking a stupid question or if my program is hard to read
There is a small bug in the code. When calling the write system call edx must contain the length of the string to be written. However, in the case that the comparison strings have the same length (the true: case), your code is:
true:
mov ecx,Two
mov edx,One
int 80H
but One refers to the string "First", not the length of string Two.
Fix it by changing it to:
true:
mov ecx,Two
mov edx,TwoLen
int 80H
I have written an assembly code to print numbers from 1 to 9 but the code only prints 1 and no other element other than 1 is printed and only one output is received.It means that the loop is also not being run. I cant figure out what is wrong with my code.
section .bss
lena equ 1024
outbuff resb lena
section .data
section .text
global _start
_start:
nop
mov cx,0
incre:
inc cx
add cx,30h
mov [outbuff],cx
cmp cx,39h
jg done
cmp cx,39h
jl print
print:
mov rax,1 ;sys_write
mov rdi,1
mov rsi,outbuff
mov rdx,lena
syscall
jmp incre
done:
mov rax,60 ;sys_exit
mov rdi,0
syscall
My OS is 64 bit linux. this code is built using nasm with the following commands : nasm -f elf64 -g -o num.o num.asm and ld -o num num.asm
Answer rewritten after some experimentation.
There two errors in your code, and a few inefficiencies.
First, you add 0x30 to the number (to turn it from the number 1 to the ASCII 1). However, you do that increment inside the loop. As a result, your first iteration cx is 0x31, second 0x62 ("b"), third 0x93 (invalid UTf-8 sequence) etc.
Just initialize cx to 0x30 and remove the add from inside the loop.
But there's another problem. RCX is clobbered during system calls. Replacing cx with r12 causes the program to work.
In addition to that, you pass the buffer's length to write, but it only has one character. The program so far:
section .bss
lena equ 1024
outbuff resb lena
section .data
section .text
global _start
_start:
nop
mov r12,30h
incre:
inc r12
mov [outbuff],r12
cmp r12,39h
jg done
cmp r12,39h
jl print
print:
mov rax,1 ;sys_write
mov rdi,1
mov rsi,outbuff
mov rdx,1
syscall
jmp incre
done:
mov rax,60 ;sys_exit
mov rdi,0
syscall
Except even now, the code is extremely inefficient. You have two compares on the same condition, one of them branches to the very next instruction.
Also, your code would be much much much faster and smaller if you moved the breaking condition to the end of the code. Also, cx is a 16 bit register. r12 is a 64 bit register. We actually only need 8 bits. Using larger registers than needed means all of our immediates waste up space in memory and the cache. We therefor switch to the 8 bit variant of r12. After these changes, we get:
section .bss
lena equ 1024
outbuff resb lena
section .data
section .text
global _start
_start:
nop
mov r12b,30h
incre:
inc r12b
mov [outbuff],r12b
mov rax,1 ;sys_write
mov rdi,1
mov rsi,outbuff
mov rdx,1
syscall
cmp r12b,39h
jl incre
mov rax,60 ;sys_exit
mov rdi,0
syscall
There's still lots more you can do. For example, you call the write system call 9 times, instead of filling the buffer and then calling it once (despite the fact that you've allocated a 1024 bytes buffer). It will probably be faster to initialize r12 with zero (xor r12, r12) and then add 0x30. (not relevant for the 8 bit version of the register).
The tutorial I am following is for x86 and was written using 32-bit assembly, I'm trying to follow along while learning x64 assembly in the process. This has been going very well up until this lesson where I have the following simple program which simply tries to modify a single character in a string; it compiles fine but segfaults when ran.
section .text
global _start ; Declare global entry oint for ld
_start:
jmp short message ; Jump to where or message is at so we can do a call to push the address onto the stack
code:
xor rax, rax ; Clean up the registers
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
; Try to change the N to a space
pop rsi ; Get address from stack
mov al, 0x20 ; Load 0x20 into RAX
mov [rsi], al; Why segfault?
xor rax, rax; Clear again
; write(rdi, rsi, rdx) = write(file_descriptor, buffer, length)
mov al, 0x01 ; write the command for 64bit Syscall Write (0x01) into the lower 8 bits of RAX
mov rdi, rax ; First Paramter, RDI = 0x01 which is STDOUT, we move rax to ensure the upper 56 bits of RDI are zero
;pop rsi ; Second Parameter, RSI = Popped address of message from stack
mov dl, 25 ; Third Parameter, RDX = Length of message
syscall ; Call Write
; exit(rdi) = exit(return value)
xor rax, rax ; write returns # of bytes written in rax, need to clean it up again
add rax, 0x3C ; 64bit syscall exit is 0x3C
xor rdi, rdi ; Return value is in rdi (First parameter), zero it to return 0
syscall ; Call Exit
message:
call code ; Pushes the address of the string onto the stack
db 'AAAABBBNAAAAAAAABBBBBBBB',0x0A
This culprit is this line:
mov [rsi], al; Why segfault?
If I comment it out, then the program runs fine, outputting the message 'AAAABBBNAAAAAAAABBBBBBBB', why can't I modify the string?
The authors code is the following:
global _start
_start:
jmp short ender
starter:
pop ebx ;get the address of the string
xor eax, eax
mov al, 0x20
mov [ebx+7], al ;put a NULL where the N is in the string
mov al, 4 ;syscall write
mov bl, 1 ;stdout is 1
pop ecx ;get the address of the string from the stack
mov dl, 25 ;length of the string
int 0x80
xor eax, eax
mov al, 1 ;exit the shellcode
xor ebx,ebx
int 0x80
ender:
call starter
db 'AAAABBBNAAAAAAAABBBBBBBB'0x0A
And I've compiled that using:
nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>
But even that causes a segfault, images on the page show it working properly and changing the N into a space, however I seem to be stuck in segfault land :( Google isn't really being helpful in this case, and so I turn to you stackoverflow, any pointers (no pun intended!) would be appreciated
I would assume it's because you're trying to access data that is in the .text section. Usually you're not allowed to write to code segment for security. Modifiable data should be in the .data section. (Or .bss if zero-initialized.)
For actual shellcode, where you don't want to use a separate section, see Segfault when writing to string allocated by db [assembly] for alternate workarounds.
Also I would never suggest using the side effects of call pushing the address after it to the stack to get a pointer to data following it, except for shellcode.
This is a common trick in shellcode (which must be position-independent); 32-bit mode needs a call to get EIP somehow. The call must have a backwards displacement to avoid 00 bytes in the machine code, so putting the call somewhere that creates a "return" address you specifically want saves an add or lea.
Even in 64-bit code where RIP-relative addressing is possible, jmp / call / pop is about as compact as jumping over the string for a RIP-relative LEA with a negative displacement.
Outside of the shellcode / constrained-machine-code use case, it's a terrible idea and you should just lea reg, [rel buf] like a normal person with the data in .data and the code in .text. (Or read-only data in .rodata.) This way you're not trying execute code next to data, or put data next to code.
(Code-injection vulnerabilities that allow shellcode already imply the existence of a page with write and exec permission, but normal processes from modern toolchains don't have any W+X pages unless you do something to make that happen. W^X is a good security feature for this reason, so normal toolchain security features / defaults must be defeated to test shellcode.)
This is the code I have and it works fine:
section .bss
bufflen equ 1024
buff: resb bufflen
whatread: resb 4
section .data
section .text
global main
main:
nop
read:
mov eax,3 ; Specify sys_read
mov ebx,0 ; Specify standard input
mov ecx,buff ; Where to read to...
mov edx,bufflen ; How long to read
int 80h ; Tell linux to do its magic
; Eax currently has the return value from linux system call..
add eax, 30h ; Convert number to ASCII digit
mov [whatread],eax ; Store how many bytes has been read to memory at loc **whatread**
mov eax,4 ; Specify sys_write
mov ebx,1 ; Specify standart output
mov ecx,whatread ; Get the address of whatread to ecx
mov edx,4 ; number of bytes to be written
int 80h ; Tell linux to do its work
mov eax, 1;
mov ebx, 0;
int 80h
Here is a simple run and output:
koray#koray-VirtualBox:~/asm/buffasm$ nasm -f elf -g -F dwarf buff.asm
koray#koray-VirtualBox:~/asm/buffasm$ gcc -o buff buff.o
koray#koray-VirtualBox:~/asm/buffasm$ ./buff
p
2koray#koray-VirtualBox:~/asm/buffasm$ ./buff
ppp
4koray#koray-VirtualBox:~/asm/buffasm$
My question is: What is with these 2 instructions:
mov [whatread],eax ; Store how many byte reads info to memory at loc whatread
mov ecx,whatread ; Get the address of whatread in ecx
Why the first one works with [] but the other one without?
When I try replacing the second line above with:
mov ecx,[whatread] ; Get the address of whatread in ecx
the executable will not run properly, it will not shown anything in the console.
Using brackets and not using brackets are basically two different things:
A bracket means that the value in the memory at the given address is meant.
An expression without a bracket means that the address (or value) itself is meant.
Examples:
mov ecx, 1234
Means: Write the value 1234 to the register ecx
mov ecx, [1234]
Means: Write the value that is stored in memory at address 1234 to the register ecx
mov [1234], ecx
Means: Write the value stored in ecx to the memory at address 1234
mov 1234, ecx
... makes no sense (in this syntax) because 1234 is a constant number which cannot be changed.
Linux "write" syscall (INT 80h, EAX=4) requires the address of the value to be written, not the value itself!
This is why you do not use brackets at this position!