Im trying to run this shellcode but it throws me: "Segmentation fault" error
The shellcode is the following:
shellcode.asm:
global _start
_start:
jmp short ca
doit:
pop ebx
xor eax, eax
cdq
mov byte [ebx+7], al
mov long [ebx+8], ebx
mov long [ebx+12], eax
lea ecx, [ebx+8]
mov byte al, 0x0b
int 0x80
ca:
call doit
db '/bin/sh'
i compile it with : 'nasm -f elf shellcode.asm'
and link it with: ' ld -m elf_i386 -s -o shellcode shellcode.o
I think the error is when I use mov [ebx+x], al/eax/ebx
because when I erase it from the code y get no error
Thank you
Your problem is that the .text section is not writable by default. The easiest thing to do is put your code into a new custom section that is marked as writable. Add this line at the top of your asm file:
section .shellcode progbits alloc exec write align=16
You could also pass the -N switch to the linker.
Alternatively, you could rewrite the shellcode so that it uses the stack to create the arguments.
Related
I coding assembly with Nasm, i want debug the program using gdb, but it not works when i put a breakpoint and run the program.
The program compile fine and link too, the problem is gdb.
Here is the commands to compile:
nasm -f elf64 -F dwarf -g types.asm
nasm -f elf64 -F dwarf -g functions.asm
nasm -f elf64 -F dwarf -g Hello.asm
ld -g -o Hello Hello.o functions.o types.o
This is the file i want debug Hello.asm:
%include "functions.asm"
section .bss
res: resb 1
fout: resb 1
section .text
global _start: ;must be declared for linker (ld)
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
filename db 'hello.txt'
_start: ;tells linker entry point
mov ecx,5
mov edx,4
call sum
mov [res],eax
mov edx,1 ;message length
mov ecx,res ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
write_string msg,len
create_file filename
mov [fout],eax
close_file [fout]
call print_msg
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
sum:
mov eax,ecx
add eax,edx
add eax,'0'
ret
Next i open gdb:
gdb Hello
(gdb) break _start
Function «_start» not defined
¿Compilación de breakpoint pendiente hasta futura cargada de biblioteca compartida? (y or [n]) y
Punto de interrupción 1 (_start) pendiente.
(gdb) run
Starting program: /asm/Hello
9Hello, world!
Hello, world!from another file
[Inferior 1 (process 5811) exited with code 01]
(gdb)
I solved it, i only change position section .data to section .text and the debugger works.I don't know why, but now the gdb take the .start.
I'm trying to execute a shell with shellcode. I've made this code in a 64-bits machine:
section .text
global _start
_start:
xor rax, rax
push rax
mov rbx, "/bin//sh"
push rbx
mov rdi, rsp
mov al, 59
syscall
mov al, 60
xor rdi, rdi
syscall
After using nasm and linking with ld if i execute the file this works fine. The problem is if i get the shellcode from this and tried to execute it with this program:
int main(){
char *shellcode = "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05\xb0\x3c\x48\x31\xff\x0f\x05";
(*(void(*)()) shellcode)();
}
It gives me a segmentation fault error. I can't see what's wrong here. Any help would be appreciated.
EDIT: Already tried the gcc -z execstack to make the stack executable, still gives a segmentation fault error
It is normal, because your shellcode is not setting the registers rsi and rdx, and when your C program executes the shellcode will have garbage in the registers rdi and rdx. It is because the syscall execve needs more arguments.
int execve (const char *filename, const char *argv [], const char *envp[]);
As extra information, the segmentation fault is because after your execve syscall you will get an error in rax and you will move 60 to the last 8 bits of rax and call to this syscall that doesn't exist.
I'm trying to write some assembly programs using nasm on linux. Everything is good, but I make heavy use of local symbols (.loop, .else, etc.), which is a pain when debugging, because these symbols are emitted to the symbol table, e.g.:
[BITS 32]
global main
section .text
main:
do stuff
.else:
do other stuff
will produce a disassembly that looks like:
<main>:
00000000 do stuff
<main.else>:
00000000 do other stuff
which is a bit annoying just because gdb will think these are all separate functions, so when I 'disas' it will only disassemble a couple of instructions before it runs into another label and stops.
Is there a way to suppress emitting these symbols to the ELF symbol table using nasm under linux?
I haven't found a way to do it directly with nasm, however if you link your object with ld, then you have at your disposal a very handy switch.
Quoting from ld's man page:
-x --discard-all
Delete all local symbols.
-X --discard-locals
Delete all temporary local symbols. (These symbols start with
system-specific local label prefixes, typically .L for ELF
systems or L for traditional a.out systems.)
so if you have, for example, this:
section .data
hello: db 'Hello world!',10
helen: equ $-hello
hi: db 'Hi!',10
hilen: equ $-hi
section .text
global _start
_start:
mov eax,4
mov ebx,1
mov ecx,hello
mov edx,helen
int 80h
.there:
mov eax,4
mov ebx,1
mov ecx,hi
mov edx,hilen
int 80h
.end:
mov eax,1
mov ebx,0
int 80h
and then build, link (and run) it like this:
$ nasm -g -f elf32 prog.asm && ld -x prog.o -o prog && ./prog
Hello world!
Hi!
then, when you load it in gdb, you get this:
$ gdb prog
.....
Reading symbols from prog...done.
(gdb) disas _start
Dump of assembler code for function _start:
0x08048080 <+0>: mov $0x4,%eax
0x08048085 <+5>: mov $0x1,%ebx
0x0804808a <+10>: mov $0x80490b8,%ecx
0x0804808f <+15>: mov $0xd,%edx
0x08048094 <+20>: int $0x80
0x08048096 <+22>: mov $0x4,%eax
0x0804809b <+27>: mov $0x1,%ebx
0x080480a0 <+32>: mov $0x80490c5,%ecx
0x080480a5 <+37>: mov $0x4,%edx
0x080480aa <+42>: int $0x80
0x080480ac <+44>: mov $0x1,%eax
0x080480b1 <+49>: mov $0x0,%ebx
0x080480b6 <+54>: int $0x80
End of assembler dump.
(gdb)
where the disassembly is not hindered by the local symbols any more.
Following this thread, How do i read single character input from keyboard using nasm (assembly) under ubuntu? ,I'm trying to compile a program that echoes the input in NASM.
I've made following files:
my_load2.asm:
%include "testio.inc"
global _start
section .text
_start: mov eax, 0
call canonical_off
call canonical_on
testio.inc:
termios: times 36 db 0
stdin: equ 0
ICANON: equ 1<<1
ECHO: equ 1<<3
canonical_off:
call read_stdin_termios
; clear canonical bit in local mode flags
push rax
mov eax, ICANON
not eax
and [termios+12], eax
pop rax
call write_stdin_termios
ret
echo_off:
call read_stdin_termios
; clear echo bit in local mode flags
push rax
mov eax, ECHO
not eax
and [termios+12], eax
pop rax
call write_stdin_termios
ret
canonical_on:
call read_stdin_termios
; set canonical bit in local mode flags
or dword [termios+12], ICANON
call write_stdin_termios
ret
echo_on:
call read_stdin_termios
; set echo bit in local mode flags
or dword [termios+12], ECHO
call write_stdin_termios
ret
read_stdin_termios:
push rax
push rbx
push rcx
push rdx
mov eax, 36h
mov ebx, stdin
mov ecx, 5401h
mov edx, termios
int 80h
pop rdx
pop rcx
pop rbx
pop rax
ret
write_stdin_termios:
push rax
push rbx
push rcx
push rdx
mov eax, 36h
mov ebx, stdin
mov ecx, 5402h
mov edx, termios
int 80h
pop rdx
pop rcx
pop rbx
pop rax
ret
Then I run:
[root#localhost asm]# nasm -f elf64 my_load2.asm
[root#localhost asm]# ld -m elfx86_64 my_load2.o -o my_load2
When I try to run it i get:
[root#localhost asm]# ./my_load2
Segmentation fault
Debugger says:
(gdb) run
Starting program: /root/asm/my_load2
Program received signal SIGSEGV, Segmentation fault.
0x00000000004000b1 in canonical_off ()
Can someone explain why is it crashing without on "import" step?
Also, I am running RHEL in Virtualbox under Win7 64 bit. Can this cause problems with compilation?
Firstly, let's address the issue of not exiting, as mentioned by Daniel. Let's comment out the two call instructions, so the program essentially does nothing:
%include "testio.inc"
global _start
section .text
_start: mov eax, 0
;call canonical_off
;call canonical_on
When we run this:
$ ./my_load2
Segmentation fault (core dumped)
It still dies! Daniel is right - you need to exit:
%include "testio.inc"
global _start
section .text
_start: mov eax, 0
;call canonical_off
;call canonical_on
mov eax, 1
mov ebx, 0
int 0x80
This time:
$ ./my_load2
$
No segfault. So let's uncomment the calls:
%include "testio.inc"
global _start
section .text
_start: mov eax, 0
call canonical_off
call canonical_on
mov eax, 1
mov ebx, 0
int 0x80
And run it again:
$ ./my_load2
Segmentation fault (core dumped)
We get a segfault again. But at least we can be (fairly) sure that's coming from inside one of the called routines.
Running the executable with strace is also quite informative:
$ strace ./my_load2
execve("./my_load2", ["./my_load2"], [/* 57 vars */]) = 0
setsockopt(0, SOL_IP, 0x400080 /* IP_??? */, NULL, 0) = -1 EFAULT (Bad address)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x40008c} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
The setsockopt line is due to the ioctl request that happens in read_stdin_termios. strace tells us the return value was EFAULT. The setsockopt(2) man page tells us this happens when:
The address pointed to by optval is not in a valid part of the process address space.
Actually this is telling us that the block of memory into which the termios structure is written is read-only. Frank is correct; everything in the program - including the termios space, and all the code - is in the read-only .text section. You can see this with:
$ objdump -h my_load2.o
my_load2.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000000cd 0000000000000000 0000000000000000 000001c0 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
i.e. there's only one section, .text, and it's READONLY.
The line that actually causes the segfault, however, is this one:
and [termios+12], eax
because it also tries to write to the (read-only) termios memory.
The quickest way to fix this is to put the termios memory in the .data section, and everything else in the .text section:
section .data
termios: times 36 db 0
section .text
stdin: equ 0
ICANON: equ 1<<1
ECHO: equ 1<<3
canonical_off:
call read_stdin_termios
[...]
(stdin, ICANON, and ECHO can be in the read-only .text section, because they're just used as constants - i.e. we don't write to those bits of memory.)
Having made these changes:
$ ./my_load2
$
The program runs and exits normally.
[section .data]
strHello db "Hello World"
STRLEN equ $-strHello
MessageLength equ 9
Message db "hi!!!! "
[section .text]
global main
main:
mov edx,STRLEN;
mov ecx,strHello;
mov ebx,1
mov eax,4
int 0x80
call DispStr
mov ebx,0
mov eax,1
int 0x80
DispStr:
mov ax,MessageLength
mov dh,0
mul dh
add ax,Message
mov bp,ax
mov ax,ds
mov es,ax
mov cx,MessageLength
mov ax,01301h
mov bx,0007h
mov dl,0
int 10h
ret
Compile and run:
$ nasm -f elf64 helloworld.asm -o helloworld.o
$ gcc -s -o helloworld helloworld.o
helloworld.o: In function `DispStr':
helloworld.asm:(.text+0x31): relocation truncated to fit: R_X86_64_16 against `.data'
collect2: ld return 1
This exact error happens because at:
add ax,Message
ax is only 16-bit wide, but Message is a 64-bit wide address, so it won't fit during relocation.
I have explained this error in detail at: https://stackoverflow.com/a/32639540/895245
The solution in this case is to use a linker script as mentioned at: Using .org directive with data in .data section: In connection with ld
This repository contains working examples of boot sectors and BIOS: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0
Since you're in 64-bit mode, you won't be able to use BIOS functions (i.e. the int 10h instruction). Even if you could, BIOS uses a different addressing mechanism, so attempting to use the address of Message wouldn't work anyway.
Also, wouldn't the first 3 lines of the DispStr function zero out ax? (since you're multiplying by dh, which was just set to zero)