Old school ascii shellcode - shellcode

This part of ascii shellcode set eax at zero with the and instruction (%...). In the debugger and in pratice this PIC code work all the time but why? the AND instruction algorithme is:
Operand target ← Operand target ∩ Operande Source
flag CF ← 0
flag OF ← 0
It's possible that the eax register is not set to zero if the previous value of eax is not good?
#include <stdlib.h>
int main()
{
asm("\
and eax, 0x454e4f4a;\
and eax, 0x3a313035;\
");
return 0;
}
compilation line:
gcc -m32 -W -Wall -std=gnu99 -masm=intel -g eaxZero.c -o eaxZero
gdb instruction:
(gdb) b 5
..
(gdb) r
..
(gdb) x/i $eip
..
(gdb) x/x $eax
..
(gdb) nexti
..
(gdb) x/x $eax
..
(gdb) nexti
..
(gdb) x/x $eax
..

Related

How can I find a proper DWARF symbol for address in a Linux kernel module?

I have a kernel module with DWARF debug info. All its ELF sections have zero start addresses.
Its DWARF info contains multiple overlapping code and data symbols. It also has many compilation units with zero DW_AT_low_pc address.
Is there a way to find the right DWARF symbol for a certain location in the binary file?
It also has many compilation units with zero DW_AT_low_pc address.
A kernel module is just a ET_REL object file. The kernel knows how to link it in into its address space.
The reason DW_AT_low_pcs are all 0s is because there are relocation entries that would have told the ld how to relocate them iff ld was to perform the link.
You could examine these entries with readelf -Wr module.ko, but it's much easier to ask GDB to do so.
Example:
// f.c
int foo(int x)
{
return x;
}
int bar(int x)
{
return foo(x);
}
gcc -c -g f.c -ffunction-sections
Resulting f.o has everything at 0:
nm f.o
0000000000000000 T bar
0000000000000000 T foo
readelf -wi f.o | grep low_pc
<1d> DW_AT_low_pc : 0x0
<35> DW_AT_low_pc : 0x0
<6c> DW_AT_low_pc : 0x0
But when loaded into GDB, you can see relocated entries (because GDB knows how to apply them):
gdb -q f.o
Reading symbols from f.o...
(gdb) p &foo
$1 = (int (*)(int)) 0x0 <foo>
(gdb) p &bar
$2 = (int (*)(int)) 0xc <bar> <<=== not 0
(gdb) disas/s foo
Dump of assembler code for function foo:
f.c:
2 {
0x0000000000000000 <+0>: push %rbp
0x0000000000000001 <+1>: mov %rsp,%rbp
0x0000000000000004 <+4>: mov %edi,-0x4(%rbp)
3 return x;
0x0000000000000007 <+7>: mov -0x4(%rbp),%eax
4 }
0x000000000000000a <+10>: pop %rbp
0x000000000000000b <+11>: retq
End of assembler dump.
(gdb) disas/s bar
Dump of assembler code for function bar:
f.c:
7 {
0x000000000000000c <+0>: push %rbp
0x000000000000000d <+1>: mov %rsp,%rbp
0x0000000000000010 <+4>: sub $0x8,%rsp
0x0000000000000014 <+8>: mov %edi,-0x4(%rbp)
8 return foo(x); <<=== correct line
0x0000000000000017 <+11>: mov -0x4(%rbp),%eax
0x000000000000001a <+14>: mov %eax,%edi
0x000000000000001c <+16>: callq 0x21 <bar+21>
9 }
0x0000000000000021 <+21>: leaveq
0x0000000000000022 <+22>: retq
End of assembler dump.

shellcode works but driver program doesnt run shellcode it just hangs

I have shellcode which run without any error in assembly,but when I put that opcode in driver program and try to invoke it, it doesnt execute that shellcode, it just hangs by running previous C instruction like printing size of shell code.
my system
physical(hardware) system is x86_64
Linux lenova 4.19.0-9-686 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) i686 GNU/Linux
gcc (Debian 8.3.0-6) 8.3.0
GNU ld (GNU Binutils for Debian) 2.31.1
NASM version 2.14
shellcode.asm
global _start
section .text
_start:
jmp msg
proc: mov al, 4
mov bl, 1
pop ecx
mov dl, 12
int 0x80
mov al, 1
mov bl, 1
int 0x80
msg: call proc
db "HellowOworld"
section .data
nasm -felf32 shellcode.asm &&
ld shellcode.o -o shellcode &&
./shellcode
HellowOworld (output)
driver.c
#include<stdio.h>
#include<string.h>
char shellcode[]="\xeb\x0f\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\xb0\x01\xb3\x01\xcd\x80\xe8\xec\xff\xff\xff\x48\x65\x6c\x6c\x6f\x77\x4f\x77\x6f\x72\x6c\x64";
int main(){
printf("Shellcode of size %d \n", (int)strlen(shellcode));
(*(void(*)())shellcode)();
}
gcc -s -fno-stack-protector -z execstack driver.c
./a.out
output=>
Shellcode of size 34
(blankline and hungs)

The value displayed in Kdbg is wrong -- NASM

How can I test to see if the value of k is correct?
section .data
k dw 5
m dw 110
rez dw 0
section .bss
tabela resq 3
section .text
global _start
extern uslov
_start:
mov qword [tabela], k
mov qword [tabela + 8], m
mov qword [tabela + 16], rez
mov rbx, tabela
call uslov
mov rax, 60
mov rdi, 0
syscall
When I try to inspect the values of k,m,rez in kdbg the values of m and rez are just fine but the value of k is totally different, now at first i thought it was random, but it seems as tough it reads the value of rez as an 8 byte number instead of a 2 byte number and also reads in 6 more bytes taking in all the set 1's from m and rez which is wrong, so how can I display it correctly ?
Screenshot:
I can reproduce this with your source (removing undefined references to uslov) when I compile using this command line:
nasm -f elf64 test.asm -o test.o
ld test.o -o test
Then, in GDB I can indeed see that k appears to have sizeof(k)==4:
gdb ./test -ex 'tb _start' -ex r -ex 'p sizeof(k)'
Reading symbols from ./test...done.
Starting program: /tmp/test
Temporary breakpoint 1, 0x00000000004000b0 in _start ()
$1 = 4
This is because the only information the final binary has about k is that it's a symbol in data area. See:
(gdb) ptype k
type = <data variable, no debug info>
The debugger (KDbg uses GDB under the hood) can't know its size, so it just guesses the default size to be sizeof(int). Even if you enable debug info in NASM via -F dwarf -g options, it still doesn't appear to put any actual debug info.
So, your only way to get the variables displayed with the right size is to manually specify it, like (short)k instead of k.

gdb seems to affect function return value that's stored in $eax?

"printf" returns the number of characters really printed, so I had:
#include<stdio.h>
int main()
{
printf("1");
printf("55555");
printf("10________");
printf("13___________");
printf("18________________");
printf("28__________________________");
}
This program will output
15555510________13___________18________________28__________________________
Then I tried to debug it in gdb and check the return value of gdb:
(gdb) b main
Breakpoint 1 at 0x804844c: file testp.c, line 4.
(gdb) r
Starting program: /home/a/cpp/a.out
Breakpoint 1, main () at testp.c:4
4 printf("1");
(gdb) n # will return "1" to $eax
5 printf("55555");
(gdb) p $eax # I expect it will print "1" here, wrong!
$1 = 49
(gdb) n
6 printf("10________");
(gdb) p $eax # I expect it will print "5" here, right!
$2 = 5
(gdb) n
7 printf("13____________");
(gdb) p $eax # I expect it will print "10" here, right!
$3 = 10
As you could see, when the first printf is run, the $eax value is not as my expectation. Later values are seems correct.
Why is this? Why first printf doesn't return a "1" to $eax? I suppose c style ABI stores return value in $eax, right?
Thanks
gcc can replace calls to printf with more efficient code, such as calls to puts or putchar, in certain cases where the optimization won't change the documented behavior of the functions (for example, when the output doesn't require any formatting to be done and you don't use the return value). That's what's happening here. You're seeing 49 in %eax because putchar returns either the character that was output, or EOF.
(gdb) disass /m main
Dump of assembler code for function main:
3 {
0x000000000040057d <+0>: push %rbp
0x000000000040057e <+1>: mov %rsp,%rbp
4 printf("1");
0x0000000000400581 <+4>: mov $0x31,%edi
0x0000000000400586 <+9>: callq 0x400450 <putchar#plt>
5 printf("55555");
0x000000000040058b <+14>: mov $0x400664,%edi
0x0000000000400590 <+19>: mov $0x0,%eax
0x0000000000400595 <+24>: callq 0x400460 <printf#plt>
To get gcc to generate calls to printf all the time, you can use the -fno-builtin-printf option.

NASM: copying a pointer from a register to a buffer in .data

I am new to asm. I am trying to copy a pointer from a register to a .data variable using NASM, on linux 64-bit.
Concider this program:
section .data
ptr: dq 0
section .text
global _start
_start:
mov [ptr], rsp
mov rax, 60
mov rdi, 0
syscall
Here I try to copy the current stack pointer to ptr. ptr is declared as a quadword. Neither nasm nor the linker complains, but when debugging the program with gdb, I can see that both addresses are different:
gdb ./test.s
+(gdb) break _start
Breakpoint 1 at 0x4000b0
+(gdb) run
Starting program: test
Breakpoint 1, 0x00000000004000b0 in _start ()
+(gdb) nexti
0x00000000004000b8 in _start ()
+(gdb) info registers
...
rsp 0x7fffffffe460 0x7fffffffe460
...
+(gdb) x ptr
0xffffffffffffe460: Cannot access memory at address 0xffffffffffffe460
From what I understand, mov should copy all 64 bits from rsp to [ptr], but it seems that the most significant 0s are not copied and/or that there is some kind of sign extension, as if only the least significant bits were copied.
The problem is, you don't have debug info for the ptr type, so gdb treats it as integer. You can examine its real contents using:
(gdb) x/a &ptr
0x600124 <ptr>: 0x7fffffffe950
(gdb) p/a $rsp
$3 = 0x7fffffffe950
Of course I have a different value for rsp than you, but you can see that ptr and rsp match.
Looks like you're using gdb wrongly to me:
section .data
ptr: dq 0
section .text
global main
main:
mov [ptr], rsp
ret
Compiling with:
rm -f test.o && nasm -f elf64 test.asm && gcc -m64 -o test test.o
Then my debugging session looks like this:
gdb ./test
(...)
(gdb) break main
Breakpoint 1 at 0x4004c0
(gdb) run
Starting program: /home/rr-/test
Breakpoint 1, 0x00000000004004c0 in main ()
(gdb) nexti
0x00000000004004c8 in main ()
(gdb) info registers
rax 0x4004c0 4195520
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe388 140737488348040
rsi 0x7fffffffe378 140737488348024
rdi 0x1 1
rbp 0x4004d0 0x4004d0 <__libc_csu_init>
rsp 0x7fffffffe298 0x7fffffffe298
(...)
(gdb) info addr ptr
Symbol "ptr" is at 0x600880 in a file compiled without debugging.
(gdb) x/g 0x600880
0x600880: 140737488347800
140737488347800 evaluates to 0x7FFFFFFFE298 just fine.
+(gdb) x/h ptr
h means half-word, which is two bytes. What you want is probably g (Giant words in GDB terminology, which is eight bytes).

Resources