execve x86 - Segmentation Fault - c

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

Related

Cannot execute 64-bit shellcode but 32-bit works fine

I am able to take a reverse shell program in assembly, compile it using ld or link (visual studio), use objdump, get the shellcode, (yes it has no null-bytes), and I am able to use this in a dropper, a simple call to it works fine such as
#include <stdio.h
#include <windows.h>
int main() {
char *shellcode = "myshellcodegoesinhere";
printf("shellcode length: %i", strlen(shellcode));
void * lpAlloc = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(lpAlloc, shellcode, strlen(shellcode));
((void(*)())lpAlloc)();
return 0;
}
However, when it comes to 64-bits, I am able to execute my programs as an exe successfully but not in a dropper like above. I literally wrote a 64-bit reverse shell in windows and it works perfectly (havent found another one online that actually works) but when I convert it to shellcode, it doesn't work in my above dropper. And yes I removed all the null bytes from it, it was quite a challenge. So then I decided to see if another simple program would behave the same way and sure enough it does. I took a simple swap mouse button program and rewrote it to remove the null bytes out of it, runs perfectly from an exe but not in a dropper. I know that my 32-bit reverse shell works in a 64-bit system. That is not the point here. The point is any 64-bit application is not able to be used as shellcode on a 64-bit machine. Here is the swap mouse button program in assembly.
BITS 64
SECTION .text
global _start
_start:
sub RSP, 0x28 ; 40 bytes of shadow space
and RSP, 0FFFFFFFFFFFFFFF0h ; Align the stack to a multiple of 16 bytes
; Parse PEB and find kernel32
xor rcx, rcx ; RCX = 0
mov rax, [gs:rcx + 0x60] ; RAX = PEB
mov rax, [rax + 0x18] ; RAX = PEB->Ldr
mov rsi, [rax + 0x20] ; RSI = PEB->Ldr.InMemOrder
lodsq ; RAX = Second module
xchg rax, rsi ; RAX = RSI, RSI = RAX
lodsq ; RAX = Third(kernel32)
mov rbx, [rax + 0x20] ; RBX = Base address
; Parse kernel32 PE
xor r8, r8 ; Clear r8
mov r8d, [rbx + 0x3c] ; R8D = DOS->e_lfanew offset
mov rdx, r8 ; RDX = DOS->e_lfanew
add rdx, rbx ; RDX = PE Header
; start a loop to inc edx 0x88 times to reach the export directory
xor rcx, rcx
xor rax, rax
mov al, 0x88 ; 136 bytes is needed to add to edx to reach the export directory
inc_edx:
inc byte edx
dec al
cmp al, cl
jne inc_edx
mov r8d, [edx] ; R8D = Offset export table
add r8, rbx ; R8 = Export table
xor rsi, rsi ; Clear RSI
mov esi, [r8 + 0x20] ; RSI = Offset namestable
add rsi, rbx ; RSI = Names table
xor rcx, rcx ; RCX = 0
mov r9, 0x41636f7250746547 ; GetProcA
; Loop through exported functions and find GetProcAddress
Get_Function:
inc rcx ; Increment the ordinal
xor rax, rax ; RAX = 0
mov eax, [rsi + rcx * 4] ; Get name offset
add rax, rbx ; Get function name
cmp QWORD [rax], r9 ; GetProcA ?
jnz Get_Function
xor rsi, rsi ; RSI = 0
mov esi, [r8 + 0x24] ; ESI = Offset ordinals
add rsi, rbx ; RSI = Ordinals table
mov cx, [rsi + rcx * 2] ; Number of function
xor rsi, rsi ; RSI = 0
mov esi, [r8 + 0x1c] ; Offset address table
add rsi, rbx ; ESI = Address table
xor rdx, rdx ; RDX = 0
mov edx, [rsi + rcx * 4] ; EDX = Pointer(offset)
add rdx, rbx ; RDX = GetProcAddress
mov rdi, rdx ; Save GetProcAddress in RDI
; Use GetProcAddress to find the address of LoadLibrary
mov rcx, 0x41797261 ; aryA
push rcx ; Push on the stack
mov rcx, 0x7262694c64616f4c ; LoadLibr
push rcx ; Push on stack
mov rdx, rsp ; LoadLibraryA
mov rcx, rbx ; kernel32.dll base address
sub rsp, 0x20 ; Allocate stack space for function call
call rdi ; Call GetProcAddress
mov rsi, rax ; LoadLibrary saved in RSI
xor rcx, rcx
push dword 0x41416c6c ; ll
;push dword rcx ; Push on the stack
sub word [rsp + 0x2], 0x4141
mov rcx, 0x642e323372657375 ; user32.d
push rcx ; Push on stack
mov rcx, rsp ; user32.dll
sub rsp, 0x20 ; Allocate stack space for function call
call rsi ; Call LoadLibraryA
mov r15, rax ; Base address of user32.dll in R15
; Call GetProcAddress(user32.dll, "SwapMouseButton")
mov rcx, 0x416e6f7474754265 ; eButton
push rcx ; Push on the stack
sub byte [rsp + 0x7], 0x41
mov rcx, 0x73756f4d70617753 ; SwapMous
push rcx ; Push on stack
mov rdx, rsp ; SwapMouseButton
mov rcx, r15 ; User32.dll base address
sub rsp, 0x20 ; Allocate stack space for function call
call rdi ; Call GetProcAddress
mov r15, rax ; SwapMouseButton in R15
; Call SwapMouseButton(true)
xor rcx, rcx ; true
inc cl
call r15 ; SwapMouseButton(true)
; Call GetProcAddress(kernel32.dll, "ExitProcess")
xor rcx, rcx ; RCX = 0
push dword 0x41737365 ; ess
sub byte [rsp + 0x3], 0x41
push rcx ; Push on the stack
mov rcx, 0x636f725074697845 ; ExitProc
push rcx ; Push on stack
mov rdx, rsp ; ExitProcess
mov rcx, rbx ; Kernel32.dll base address
sub rsp, 0x20 ; Allocate stack space for function call
call rdi ; Call GetProcAddress
; Call ExitProcess(0)
xor rcx, rcx ; Exit code 0
call rax ; ExitProcess(0)
Save this as sw64.s
link.exe (visual studio x64 native tools command prompt)
I have two linkers I use that work just fine. both link and Golink.exe
nasm -f win64 sw64.s && link sw64.obj /SUBSYSTEM:CONSOLE /OUT:sw64.exe /LARGEADDRESSAWARE:NO /ENTRY:_start && sw64.exe
or using Golink.exe
nasm -f win64 sw64.s && c:\Golink\GoLink.exe /console /entry _start sw64.obj /fo sw64.exe && sw64.exe
I then convert the shellcode using objdump and filter with awk and sed to produce \x??\x?? output and use this in my dropper. I've done it for my 32-bit reverse shell and it works like a charm but not for 64-bit. I would like to understand why this isn't working. Thank you.
converting 64-bit to shellcode does not work, but 32-bit does

Interaction with array results in a segfault

I'm trying to implement a simple addition calculator, but I'm not able to store the input in my array. I'm trying to read char by char because I want to use it later to implement a backend for my B compiler (which has the getchar function that reads char by char from stdin). My code is the fallowing:
segment .data
numb db 0, 0, 0, 0
indx db 0
char db '0'
newl db 0ah
msg1 db 'enter a number: '
len1 equ $ - msg1
segment .text
global _start ; defines the entry point
print: ; push msg; push len
pop eax ; removes caller address from stack
pop edx ; gets length
pop ecx ; gets msg
push eax ; pushes CA to stack again
mov ebx , 01h ; tells that it's an output call
mov eax , 04h ; system call (write)
int 80h ; calls it
ret
getc: ; push add; push len
pop eax ; removes caller address from stack
pop ecx ; gets ouput addrress
push eax ; pushes CA to stack again
mov edx , 01h
mov ebx , 00h ; tells that it's an input call
mov eax , 03h ; system call (read)
int 80h ; calls it
ret
exit:
mov ebx , 0 ; sets exit code
mov eax , 01h ; system call (exit)
int 80h ; calls it
_start:
push msg1
push len1
call print
read:
push char
call getc
mov eax , numb
add eax , indx
mov [eax], dword char
inc byte [indx]
mov eax , char
cmp eax , newl
jne read
jmp exit ; exits program
for now I'm just trying to store the input, because I got segfaults from the complete code, so I started stripping off code until I found the error cause.
You probably don't want to insert the newline in the array, so start with checking for the newline:
read:
push char
call getc
mov al, [char]
cmp al, 10
je done
Then load the byte-sized index in an address register, remembering that AL already contains the datum, so pick another register than EAX. Also, instead of adding the array address numb and the index indx yourself, let the CPU do that for your with an addressing mode that has a displacement component ([numb + ebx]):
movzx ebx, byte [indx]
mov [numb + ebx], al
inc byte [indx]
jmp read
done:
jmp exit
There's also the possibility to define the index indx as a dword with indx dd 0. Then the code becomes:
read:
push char
call getc
mov al, [char]
cmp al, 10
je done
mov ebx, [indx]
mov [numb + ebx], al
inc dword [indx]
jmp read
done:
jmp exit
The lesson here is that NASM is different from MASM in how you address memory:
MASM
mov eax, offset MyVar ; Load address of MyVar
mov eax, MyVar ; Load value stored in MyVar
NASM
mov eax, MyVar ; Load address of MyVar
mov eax, [MyVar] ; Load value stored in MyVar

Printing array as double word in assembly

%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
array: dd 180,32,455,499,388,480,239,346,257,84
fmt: dd ",%d",0
; uninitialized data is put in the .bss segment
;
segment .bss
resd 10
;
; code is put in the .text segment
;
segment .text
extern printf
global asm_main
asm_main:
enter 0,0 ; setup routine
pusha
; The following is just example of how to print an array
push dword 10
push dword array
call print_array
add esp,8 ; clean up stack
; don't delete anything following this comment
popa
mov eax, 0 ; return back to C
leave
ret
segment .data
ListFormat db ",%u", 0
segment .text
global print_array
print_array:
enter 0,0
push esi
push ebx
xor esi, esi ; esi = 0
mov ecx, [ebp+12] ; ecx = n
mov ebx, [ebp+8]
xor edx, edx
mov dl, [ebx + esi] ; ebx = address of array
mov eax,edx
call print_int
dec ecx
inc esi
print_loop:
xor edx,edx
mov dl,[ebx + esi]
push ecx ; printf might change ecx!
push edx ; push array value
push dword ListFormat
call printf
add esp, 8 ; remove parameters (leave ecx!)
inc esi
pop ecx
loop print_loop
call print_nl
pop ebx
pop esi
leave
ret
So this code prints out 180,0,0,0,32,0,0,0,199,1 when I want to print out 180,32,455,499,388,480,239,346,257,84. I think that it's because this is designed to print byte words. I'm trying to print in double words and I'm guessing something in the print_array needs to be changed. I tried mov dl, [ebx+esi*4] but it still doesn't print the array that I want to print. Or does something else needs to be changed to print array of double words?
You could leave it at changing the mov dl, [ebx+esi] instruction into mov edx, [ebx+esi*4], but that would be just half the fun!
1 Why not try to make a loop that can deal with the special case of the first value in the list that doesn't need the comma prefix? No more using print_int.
2 Also don't use the LOOP instruction. It's slow! The pair cmp jb (that can macro-fuse) is much better.
3 And replacing the prolog enter 0,0 and epilog leave codes by simply addressing the parameters via ESP relative addressing is simple enough.
4 Always consider the special cases! What if the array happens to be empty?
print_array:
push ebx
push esi
mov ebx, [esp+12] ; Begin array
mov esi, [esp+16] ; n
test esi, esi
jz done
lea esi, [ebx+esi*4] ; End array
mov edx, ListFormat+1 ; "%u"
more: mov eax, [ebx] ; Array dword value
push eax
push edx ; "%u" first time, ",%u" others
call printf
add esp, 8
add ebx, 4 ; To next dword in the array
mov edx, ListFormat ; ",%u"
cmp ebx, esi ; Current address < Last address ?
jb more ; Yes
call print_nl
done: pop esi
pop ebx
ret
Under the right conditions, keeping ESP fixed inside this loop can be worth doing. See Peter Cordes' comments below this answer.
Next is a version of this code that keeps ESP fixed inside the loop:
print_array:
push ebx
push esi
mov ebx, [esp+12] ; Begin array
mov esi, [esp+16] ; n
test esi, esi
jz done
sub esp, 8 ; Space for the printf args
lea esi, [ebx+esi*4] ; End array
mov edx, ListFormat+1 ; "%u"
more: mov eax, [ebx] ; Array dword value
mov [esp+4], eax
mov [esp], edx ; "%u" first time, ",%u" others
call printf
add ebx, 4 ; To next dword in the array
mov edx, ListFormat ; ",%u"
cmp ebx, esi ; Current address < Last address ?
jb more ; Yes
call print_nl
add esp, 8
done: pop esi
pop ebx
ret

Segmentation fault Core Dumped X86 Assembly Array

I asked for help earlier and thought I was home free but I'm not. My logic was wrong and I've greatly altered it. This program is supposed to return the Max int in the array (which also happens to be the last element). After tracing it with GDB a few times, I see that I get to the 5th (2nd to last) element in the array, "20", when I hit a segmentation fault and the program halts. I set ECX to the array length and subtracted 1 from ECX to avoid this, but my logic is obviously wrong. Am I wrong in depending on the ECX counter to terminate the loop. Any ideas please?
***EDIT MAJOR EDITS TO CODE
SECTION .data ;data section
msg1: db "Here are the array elements:", 10, 0
msg1Len: equ $-msg1
msg2: db "Here is the sorted array:", 10, 0
msg2Len: equ $-msg2
arr: dd 12, 16, 6, 18, 10, 40, 30
arrLen: equ ($-arr)/4 ;number of elements = array length / 4
SECTION .bss
max resd 1 ;declare and reserve space for max
SECTION .text
global bsort
bsort:
push ebp ; save old ebp register
mov ebp, esp ; build a new stack
restart:
mov ebx, arr ; the base address argument is saved in ebx register
mov ecx, arrLen ; the size argument is saved in exc register
sub ecx, 1 ; Last member has no following element to compare with.
; So we need to reduce the counter by 1
top:
mov eax, [ebx] ;; access first array element. Move its value to eax
cmp eax, [ebx+4] ; compare the value of eax ([ebx]) with [ebx+4]
jle noswap ; if value at eax is less or equal to value of [ebx+4]
; no need to exchang values. Jump to noswap
xchg eax, [ebx+4] ; if value at eax > value [ebx+4], exchange
mov [ebx], eax ; store the new exchanged value at [ebx]
jmp restart ; reset the base address and counter. Start over
noswap:
add ebx, 4 ; move to the next array element
loop top ; loop back to the top if the register ecx > 0
leave
ret
global main
main:
push ebp
mov ebp, esp
mov ecx, msg1 ;print msg1
mov edx, msg1Len
call PString
;save array base address in ebx and save sizein in ecx
mov ebx, arr
mov ecx, arrLen; store num elements in ecx
;loop to print array
PrintArray:
mov eax, [ebx] ;move value [ebx] to eax
call PrintDec
call Println
add ebx, 4
loop PrintArray
;call bubblesort
call bsort
mov ecx, msg2
mov edx, msg2Len
call PString
;save arr base add in sbx and size in ecx
mov ebx, arr
mov ecx, arrLen
PrintSortedArray:
mov eax, [ebx]
call PrintDec
call Println
add ebx, 4
loop PrintSortedArray
;exit program and clean stack
mov esp, ebp
pop ebp
ret
PString:; save register values of the called function
pusha
mov eax,4 ; use 'write' system call = 4
mov ebx,1 ; file descriptor 1 = STDOUT
int 80h ; call the kernel
; restore the old register values of the called function
popa
ret
Println:
;will call PString func
;will change content of ecx and edx
;need to save registers used by the main program
section .data
nl db 10
section .text
pusha
mov ecx, nl
mov edx, 1
call PString
;return original register values
popa
ret
PrintDec:
;saves all registers so they return unmodified
;build the function to handle dword size
section .bss
decstr resb 10 ; 10 32-bit digits
ct1 resd 1 ;keep track of dec-string size
section .text
pusha; save registers
mov dword[ct1],0 ;initially assume 0
mov edi, decstr ; edi points to dec-string
add edi, 9 ; moved to the last element of string
xor edx, edx ; clear edx for 64-bit div
whileNotZero:
mov ebx, 10 ; get ready to divide by 10
div ebx ; divide by 10
add edx, '0' ; convert to ascii
mov byte[edi], dl ; put it in string
dec edi ; move to next char in str
inc dword[ct1] ; inc char counter
xor edx, edx ; clear edx
cmp eax, 0 ;is remainder 0?
jne whileNotZero ;if no, keep on looping
inc edi ; conversion finished, bring edi
mov ecx, edi ; back to start of string. make ecx
mov edx, [ct1] ; point to counterm edx gets # chars
mov eax, 4 ; print to stdout
mov ebx, 1
int 0x80 ; call kernel
popa ; restore registers
ret

X86 Assembly Printing Max in Array returns Segmentation fault (core dumped)

My program works, but there is something wrong with my printMax function. The program terminates with a
Segmentation fault (core dumped).
I have tried building a stack for the function and just doing a pusha popa and both ways, I get the seg fault core dumped.
I've tried calling the function, but it just runs twice.
Any idea what I am doing wrong?
SECTION .data ;data section
msg1 : db "Here are the array elements:", 10, 0
msg1Len: equ $-msg1
msg2 : db "Here is the max value in the array:", 10, 0
msg2Len: equ $-msg2
arr : dd 2,4,6,8,10,20,40
arrLen : equ ($-arr)/4 ;number of elements = array length / 4
SECTION .bss
max resd 1 ;declare and reserve space for max
SECTION .text
global main
main:
push ebp
mov ebp, esp
mov ecx, msg1 ;print msg1
mov edx, msg1Len
call PString
;save array base address in ebx and save sizein in ecx
mov ebx, arr
mov ecx, arrLen; store num elements in ecx
;loop to print array
PrintArray:
mov eax, [ebx] ;move value [ebx] to eax
call PrintDec
call Println
add ebx, 4
loop PrintArray
printMax:
section .text
pusha
;reset array to find max
mov ebx, arr
mov ecx, arrLen
loopForMax:
mov eax, [ebx]
cmp eax, [ebx +4]
jle sameMax
mov [max], eax
sameMax:
add ebx, 4 ;move to next element
loop loopForMax
mov ecx, msg2
mov edx, msg2Len
call PString
mov eax, [max]
call PrintDec
call Println
popa
ret
;exit program and clean stack
mov esp, ebp
pop ebp
ret
PString:; save register values of the called function
pusha
mov eax,4 ; use 'write' system call = 4
mov ebx,1 ; file descriptor 1 = STDOUT
int 80h ; call the kernel
; restore the old register values of the called function
popa
ret
Println:
;will call PString func
;will change content of ecx and edx
;need to save registers used by the main program
section .data
nl db 10
section .text
pusha
mov ecx, nl
mov edx, 1
call PString
;return original register values
popa
ret
PrintDec:
;saves all registers so they return unmodified
;build the function to handle dword size
section .bss
decstr resb 10 ; 10 32-bit digits
ct1 resd 1 ;keep track of dec-string size
section .text
pusha; save registers
mov dword[ct1],0 ;initially assume 0
mov edi, decstr ; edi points to dec-string
add edi, 9 ; moved to the last element of string
xor edx, edx ; clear edx for 64-bit div
whileNotZero:
mov ebx, 10 ; get ready to divide by 10
div ebx ; divide by 10
add edx, '0' ; convert to ascii
mov byte[edi], dl ; put it in string
dec edi ; move to next char in str
inc dword[ct1] ; inc char counter
xor edx, edx ; clear edx
cmp eax, 0 ;is remainder 0?
jne whileNotZero ;if no, keep on looping
inc edi ; conversion finished, bring edi
mov ecx, edi ; back to start of string. make ecx
mov edx, [ct1] ; point to counterm edx gets # chars
mov eax, 4 ; print to stdout
mov ebx, 1
int 0x80 ; call kernel
popa ; restore registers
ret

Resources