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.
Related
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.
I have a basic asm program that checks if a string is a digit. I was adding in code to read from command line arguements, put it keeps seg faulting.
if what I have read is right, this should get the amount of arguments passed to the program, which should be stored in 0(%ebp). What am i doing wrong?
The entirity of the code can be found here: http://pastebin.com/kGV2Mxx4
The problem is the first 3-5 lines of _start.
upon Looking at lscpu's output, I have an i868 cpu. Although, it says it can operate in 32-bit and 64-bit. I am running 32 bit linux (Arch linux x86)
I fixed the issue. I did 2 pop's, one to bypass the programs name, the next to get the first argument. the updated code can be found here: http://pastebin.com/xewyeHYf
Can someone please tell me why I could not just do the following:
pushl 8(%ebp)
or
movl 8(%ebp), %eax
Here is a little tutorial I wrote on the subject:
NASM - Linux Getting command line parameters
You could write this:
_start:
b1: movl 0(%ebp), %eax
cmpl $1, %eax
je load_msg
b2: pushl 8(%ebp)
b4: call check
To understand why your previous attempts didn't work, draw stack diagrams.
Compile a small C program that does something like what you want to do, and compile it to assembly language to find out exactly how to access arguments. The x86_32 code doesn't look at all like any of the above, BTW:
int main(int argc, char *argv[])
{
return argv[1][0];
}
gives (yes, some is superfluous stack bookkeeping, but anyway):
.file "tst.c"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movzbl (%eax), %eax
movsbl %al, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.7.2 20121109 (Red Hat 4.7.2-8)"
.section .note.GNU-stack,"",#progbits
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
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.
as a beginner of asm, I am checking gcc -S generated asm code to learn.
why gcc 4.x default reserve 8 bytes for stack when calling a method?
func18 is the empty function with no return no param no local var defined.
I can't figure out why 8 bytes is reserved here (neither any forum/site mention for the reason, ppl seems take it for granted)
is it for the %ebp just push? or return type?! many thx!
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
.text
Some instructions require certain data types to be aligned to as much as a 16-byte boundary (in particular, the SSE data type __m128). To meet this requirement, gcc ensures that the stack is initially 16-byte aligned, and allocates stack space in multiples of 16 bytes. If only a 4-byte return address and 4-byte frame pointer need to be pushed, 8 additional bytes are needed to keep the stack aligned to a 16-byte boundary. However, if gcc determines that the additional alignment is unnecessary (i.e. the fancy data types are not used and no external functions are called), then it may omit any additional instructions used to align the stack. The analysis necessary to determine this may require certain optimization passes to be performed.
See also the gcc documentation for the option -mpreferred-stack-boundary=num.
As richard mentioned above, it's all because of optimization, showing below.
but still I got no idea why 8 bytes reserved is something optimized?!
original c
void func18() {}
int main() {return 0;}
compile without optimization flag specified
.text
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
leave
ret
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $0, %eax
leave
ret
.subsections_via_symbols
with -Os optimization flag, no more stack reserve
.text
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
leave
ret
.globl _main
_main:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
leave
ret
.subsections_via_symbols
Easy way to find out: Have you empty function call another function with one parameter. If the parameter is stored directly to the stack (no push), then that's what the extra space is for.