Shell does not open when trying to open shell with Assembly code - linux

I am trying to open a shell code using the following assembly code where I have tried to use JUMP CALL POP method.
.section .text
.globl main
main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $0xc, %esp
jmp end
hop:
popl %ebx
movl %ebx, -0xc(%ebp)
movl $0, -0x4(%ebp)
movl $59, %eax
leal -0xc(%ebp), %ecx
movl $0, %edx
int $0x80
leave
ret
end:
call hop
.asciz "/bin/sh\0"
I am running the code in x86_64 with the following commands
gcc -m32 file.s
GCC -m32 -o file file.s
./file
In this case, nothing occurs, and no shell open up.
What might be the possible issue in my code? Debugging with gdb indicates that %ebx and %eax are correctly loaded. But still the shell does not open up.

Related

Why is GDB breakpoint set at the wrong address for an x86 assembly function?

I am experiencing an issue where gdb is mapping a line number to the wrong memory address when adding a breakpoint.
The following x86 Linux assembly program prints "hello".
/* hello.s */
.section .data
str:
.ascii "hello\n"
strlen = . - str
.section .text
print:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl $4, %eax
movl $1, %ebx
movl $str, %ecx
movl $strlen, %edx
int $0x80
popl %ebx
movl %ebp, %esp
popl %ebp
ret
.globl _start
_start:
call print
movl $1, %eax
movl $0, %ebx
int $0x80
I compile it with debugging information, and then link.
$ as -g --32 -o hello.o hello.s
$ ld -m elf_i386 -o hello hello.o
Next, in gdb, I try to set a breakpoint on line 11, the first line of the print function (pushl %ebp).
$ gdb ./hello
(gdb) break hello.s:11
Breakpoint 3 at 0x8048078: file hello.s, line 11.
As shown in the output, the breakpoint is set at address 0x8048078. However, that is the wrong address. When I run my program in gdb, it breaks at line 14. The address of line 11 is 0x8048074, confirmed using gdb's info command.
(gdb) info line hello.s:11
Line 11 of "hello.s" starts at address 0x8048074 and ends at 0x8048075 .
Setting a breakpoint on the print instruction directly works (the break point is set for the address of line 11, 0x8048074).
How come when I add a breakpoint for line 11, gdb does not use the same address as output by using the info command above? This is the memory address I am trying to break on.
I am experiencing the same behavior on both gdb 7.11.1 and 8.0.1. I have tried adding a .type print,#function annotation, but that did not solve my issue.
How come
By default, GDB tries to skip past function prolog, when you set a breakpoint on a function, or a line on which the function starts.
This tends to be what C developers want, since they usually aren't interested in parameter setup.
If you want something else, use b *address or b &print to prevent GDB from doing its usual thing.

Compiling Linux assembler on Windows

.string "Hello\n"
.globl main
main:
pushl %ebp
movl %esp, %ebp
pushl $hello
call puts
movl $0, %eax
movl %ebp, %esp
popl %ebp
ret
This code works on 32bit Linux. How can I run this on Windows?
gcc hello.s
You need to find a Windows version of an x86 assembler. The GNU Assembler is available on Windows through the MinGW project. This is the same assembler you are using on Linux.

Still getting segmentation fault after calling mprotect in self-modifying assembly code

I'm trying to learn some stack overflow techniques and use shellcode in them.
I was able to successfully use some basic shellcodes. Then I started working on using exeve in assembly and invoke ls -l with that, again successful.
Now I am trying to use relative addressing and get rid of null values in my code. Because of that I tried a simple self-modifying code. I know code segment is read-only so I tried calling mprotect to make it writable. My code still doesn't work and I get segmentation fault at movb %al, 0x7(%esi). I really appreciate it if someone could give me some insight into the thing that is wrong in my code.
.text
.globl _start
_start:
jmp StartPoint
execvecall:
popl %esi # the address of string
#calling mprotect to make the memory writable
movl $0x7d, %eax
movl %esi, %ebx
movl $0x20, %ecx
movl $7, %edx
int $0x80
xorl %eax, %eax
movb %al, 0x7(%esi) #putting zero for at the end of /bin/ls
movb %al, 0xa(%esi) #putting another zero at the end of -l
#this part forms an array ending with for the second parameter of execve
movl %esi, 0xb(%esi)
movl %esi, %ebx
addl $8, %ebx
movl %ebx, 0xf(%esi)
movl %eax, 0x13(%esi)
movl %esi, %ebx
leal 0xb(%esi), %ecx
leal 0x13(%esi), %edx
movb $11, %al
int $0x80
StartPoint:
call execvecall
SomeVarHere:
.ascii "/bin/ls0-l0111122223333"
man mprotect says:
The implementation may require that addr be a multiple of the page size as returned by sysconf().
This is apparently the case on your machine. Assuming you have 4 KiB pages (as on x86, no PSE), you can round the address down by executing
and $0xfffff000, %ebx
after
movl %esi, %ebx
when preparing to call mprotect.
Note that calling mprotect changes the protection for the whole page.

ASM call Printf

movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
I use the following asm code to print what is in EBX register. When I use
movl $1,%eax
int 0x80
and the echo $? I get the correct answer but segmentation fault in the first case. I am using the GNU Assembler and AT&T syntax. How can I fix this problem?
Judging by the code, you are probably in 64 bit mode (please confirm) in which case pointers are 64 bit in size. In a position-depended executable on Linux movl $.LC1, %edi is safe and what compilers use, but to make your code position-independent and able to handle symbol addresses being outside the low 32 bits you can use leaq .LC1(%rip), %rdi.
Furthermore, make sure that:
you are preserving value of rbx in your function
stack pointer is aligned as required
This code works for me in 64 bit:
.globl main
main:
push %rbx
movl $42, %ebx
movl %ebx, %esi
leaq .LC1(%rip), %rdi
movl $0, %eax
call printf
xor %eax, %eax
pop %rbx
ret
.data
.LC1: .string "%d\n"
Edit: As Jester noted, this answer only applies to x86 (32 bits) asm whereas the sample provided is more likely for x86-64.
That's because printf has a variable number of arguments. The printf call doesn't restore the stack for you, you need to do it yourself.
In your example, you'd need to write (32 bits assembly):
push %ebx
push $.LC1
call printf
add $8, %esp // 8 : 2 argument of 4 bytes

Invalid instruction suffix for push when assembling with gas

When assembling a file with GNU assembler I get the following error:
hello.s:6: Error: invalid instruction suffix for `push'
Here's the file that I'm trying to assemble:
.text
LC0:
.ascii "Hello, world!\12\0"
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
What is wrong here and how do I fix it?
The problem is somewhat related to this question although errors and instructions in questions are different.
Prepend .code32 as your first line.
--32 option will change the target to 32 bit platform.
64bit instructions
By default most operations remain 32-bit and the 64-bit counterparts are invoked by the fourth bit in the REX prefix. This means that each 32-bit instruction has it's natural 64-bit extension and that extended registers are for free in 64-bit instructions
movl $1, %eax # 32-bit instruction
movq $1, %rax # 64-bit instruction
pushl %eax # Illegal instruction
pushq %rax # 1 byte instruction encoded as pushl %eax in 32 bits
pushq %r10 # 2 byte instruction encoded as pushl preceeded by REX
Are you assembling with a 64-bit assembler? Your code looks like it's 32-bit. I get this error with your code when using a 64-bit assembler:
example.s:6:suffix or operands invalid for `push'
But it works fine with a 32-bit assembler.
You have to use a "64 bit syntax", or you can use the " --32 " option: by this way the assembler chages its target to the i386 platform.

Resources