GRUB error 13: invalid or unsupported executable format on custom kernel - operating-system

I am trying to learn OS Dev and I started building my own kernel based on The Little book about OS Development.
When I loaded the kernel using bochs GRUB complains with:
error 13: invalid or unsupported executable format
The files I'm using:
loader.s
global loader
MAGIC_NUMBER equ 0xBADB002
FLAGS equ 0x0
CHECKSUM equ -MAGIC_NUMBER
section .text
align 4
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM
loader:
mov eax, 0xCAFEBABE
.loop:
jmp .loop
link.ld
ENTRY(loader)
SECTIONS
{
. = 0x00100000;
.text ALIGN (0x1000) :
{
*(.text)
}
.rodata ALIGN (0x1000) :
{
*(.rodata*)
}
.data ALIGN (0x1000) :
{
*(.data)
}
.bss ALIGN (0x1000) :
{
*(COMMON)
*(.bss)
}
}
bochsrc.txt
megs: 32
display_library: sdl
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=os.iso, status=inserted
boot: cdrom
log: bochslog.txt
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000
menu.lst
default=0
timeout=0
title First OS
kernel /boot/kernel.elf
commands to execute:
nasm -f elf32 loader.s
ld -T link.ld -melf_i386 loader.o -o kernel.elf
genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -A os -input-charset utf8 -quiet -boot-info-table -o os.iso iso
bochs -f bochsrc.txt
My files structure is like this:
os_dev
|--(rest of the files)
|--iso
|-- boot
|-- kernel.elf
|-- grub
|-- menu.lst
|-- stage2_eltorito
The file stage2_eltorito was downloaded from https://github.com/littleosbook/littleosbook/blob/master/files/stage2_eltorito

Michael Petch noticed that B. Kostas was using an incorrect Magic Number for Grub Legacy.
Changing MAGIC_NUMBER equ 0xBADB002 in loader.s to MAGIC_NUMBER equ 0x1BADB002 solved the issue.

Related

Set virtual address of section to custom byte

I'm trying to put a small boot loader into the mbr of an exfat drive, but I'm having trouble getting ld to set the virtual address correctly.
according to the ExFat Specification, I need to put the bootloader at byte 0x78 (120). So I set the location counter to 0x7C78. But when I used readelf on the result, I found that ld put the virtual address at 0x7C80 instead.
This is sadly not what I want, so I tried to set the virtual address to different values and found that ld will always put the section with a 16 byte alignment. e.g. at 0x7C70 and 0x7C80
My question is: Is there any way to disable/override this alignment, and put my section at the specific address
The boot code
bits 16
global boot
boot:
mov ax, 0x0202
mov bx, 0x7E00
mov cx, 0x0002
mov dx, 0x0080
int 0x13
jmp 0x0000:0x7e00
times 388-($-$$) db 0x00
dw 0xAA55
The linkerscript
OUTPUT_FORMAT("binary")
SECTIONS {
. = 0x7c78;
.text :
{
*.mbr.o(.text)
}
.text :
{
*.o(.text)
}
}
The readelf result
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS src/boot/boot.mbr.s
2: 0000000000000000 0 SECTION LOCAL DEFAULT 4 .debug_info
3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .debug_abbrev
4: 0000000000000000 0 SECTION LOCAL DEFAULT 6 .debug_line
5: 0000000000007c93 1 OBJECT LOCAL DEFAULT 1 boot.end
6: 0000000000000000 0 FILE LOCAL DEFAULT ABS src/boot/boot.s
7: 0000000000007e10 0 SECTION LOCAL DEFAULT 2 .text
wrong > 0000000000007c80 0 NOTYPE GLOBAL DEFAULT 1 boot
9: 0000000000007e10 0 NOTYPE GLOBAL DEFAULT 2 stage2
I used these flags to call nasm:
nasm -felf64 -g -F dwarf -o boot.mbr.o boot.mbr.s
and these flags to call ld
i386-elf-gcc -nostdlib -n -Wl,--oformat=elf64-little -T linker.ld -o boot.elf boot.mbr.o

How to change a mac address using the command line parameters in the linux kernel

I want to change a mac address at the u-boot level like the following.
# setenv bootargs 'console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}'
# setenv ethaddr 11:22:33:44:55:66
# saveenv
And at the driver,
static unsigned char my_ethaddr[MAX_ADDR_LEN];
/* need to get the ether addr from armboot */
static int __init ethaddr_setup(char *line)
{
char *ep;
int i;
printk("command line : %s\n", line);
memset(my_ethaddr, 0, MAX_ADDR_LEN);
/* there should really be routines to do this stuff */
for (i = 0; i < 6; i++)
{
my_ethaddr[i] = line ? simple_strtoul(line, &ep, 16) : 0;
if (line)
line = (*ep) ? ep+1 : ep;
printk("mac[%d] = 0x%02Xn", i, my_ethaddr[i]);
}
return 0;
}
__setup("ethaddr=", ethaddr_setup);
When booting, the log message is like following.
[ 0.000000] Kernel command line: console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}
[ 0.000000] command line : ${ethaddr}
[ 0.000000] mac[0] = 0x00, mac[1] = 0x00, mac[2] = 0x0E, mac[3] = 0x00, mac[4] = 0xDD, mac[5] = 0x00
The command line message is ${ethaddr}, is it right?
The mac address isn't correct.
How can I fix it?
You are using single quotes in:
setenv bootargs '... ethaddr=${ethaddr}'
so ${ethaddr} is not expanded and the bootargs variable contains the literal string ethaddr=${ethaddr}, which is then passed into the kernel and is what you see in your debug output. See the U-Boot documentation on How the Command Line Parsing Works for more details.
You could use double quotes, or no quotes at all, in which case ${ethaddr} would be expanded when assigning to bootargs, although you would need to set it first:
# setenv ethaddr 11:22:33:44:55:66
# setenv bootargs console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=${ethaddr}
# printenv bootargs
bootargs=console=ttyAMA0,115200n8 root=/dev/ram0 rw initrd=0x40000000 ethaddr=11:22:33:44:55:66
Note that in some systems the ethaddr variable is used by U-Boot itself to configure the MAC address of the first network device, and the Linux network driver may continue to use that address, so you don't need to explicitly pass it into the kernel. See the documentation on U-Boot Environment Variables.
In addition U-Boot may be configured to prevent modification of the ethaddr variable, although that's probably not the case here because when it is U-Boot prints the error message:
Can't overwrite "ethaddr"

Segfault when running hello world shellcode in C program

sorry if this question sounds dumb but I am very new to shellcoding and I was trying to get a hello world example to work on a 32 bit linux machine.
As this is shellcoding, I used a few tricks to remove null bytes and shorten the code. Here it is:
section .data
section .text
global _start
_start:
;Instead of xor eax,eax
;mov al,0x4
push byte 0x4
pop eax
;xor ebx,ebx
push byte 0x1
pop ebx
;xor ecx,ecx
cdq ; instead of xor edx,edx
;mov al, 0x4
;mov bl, 0x1
mov dl, 0x8
push 0x65726568
push 0x74206948
;mov ecx, esp
push esp
pop ecx
int 0x80
mov al, 0x1
xor ebx,ebx
int 0x80
This code works fine when I compile and link it with the following commands:
$ nasm -f elf print4.asm
$ ld -o print4 -m elf_i386 print4.o
However, I tried running it within the following C code:
$ cat shellcodetest.c
#include
#include
char *shellcode = "\x04\x6a\x58\x66\x01\x6a\x5b\x66\x99\x66\x08\xb2\x68\x68\x68\x65\x69\x48\x54\x66\x59\x66\x80\xcd\x01\xb0\x31\x66\xcd\xdb\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c –m32 –z execstack -o shellcodetest
$ ./shellcodetest
Segmentation fault (core dumped)
Could someone please explain what is happening there? I tried running the code in gdb and noticed something weird happening with esp. But as I said before, I still lack experience to really understand what is going on here.
Thanks in advance!
Your shellcode does not work, because it is not entered in the correct endianness. You did not state how you extracted the bytes from the file print4, but both objdump and xxd gives the bytes in correct order.
$ xxd print4 | grep -A1 here
0000060: 6a04 586a 015b 99b2 0868 6865 7265 6848 j.Xj.[...hherehH
0000070: 6920 7454 59cd 80b0 0131 dbcd 8000 2e73 i tTY....1.....s
$ objdump -d print4
print4: file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
8048060: 6a 04 push $0x4
8048062: 58 pop %eax
8048063: 6a 01 push $0x1
...
The changes you need to do is to swap the byte order, '\x04\x6a' -> '\x6a\x04'.
When I run your code with this change, it works!
$ cat shellcodetest.c
char *shellcode = "\x6a\x04\x58\x6a\x01\x5b\x99\xb2\x08\x68\x68\x65\x72\x65\x68\x48\x69\x20\x74\x54\x59\xcd\x80\xb0\x01\x31\xdb\xcd\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c -m32 -z execstack -o shellcodetest
$ ./shellcodetest
Hi there$

Analyzing binary taken from memory dump in IDA Pro

I'm having problems with analyzing a simple binary in IDA Pro.
When running a program, i dumped part of its memory (for example, unpacked code section in the memory) into a file, using WinDbg.
I would like to analyze it using IDA, but when trying to just load the binary - it will only show its raw data.
Of course the binary is not a full PE file, so I'm not expecting a deep analysis, just a nicer way to read the disassembly.
So the question is - How can i make IDA disassemble the binary?
Thanks! :)
select an appropriate address and press c
that is MakeCode(Ea); ida will convert the raw bytes to code and disassemble it
pasted below is a simple automation with an idc script but idas automation is imho subpar so you should stick with manual pressing of C in user interface
:dir /b
foo.dmp
foo.idc
:xxd foo.dmp
0000000: 6a10 6830 b780 7ce8 d86d ffff 8365 fc00 j.h0..|..m...e..
0000010: 64a1 1800 0000 8945 e081 7810 001e 0000 d......E..x.....
0000020: 750f 803d 0850 887c 0075 06ff 15f8 1280 u..=.P.|.u......
0000030: 7cff 750c ff55 0850 e8c9 0900 00 |.u..U.P.....
:type foo.idc
#include <idc.idc>
static main (void) {
auto len,temp,fhand;
len = -1; temp = 0;
while (temp < 0x3d && len != 0 ) {
len = MakeCode(temp);
temp = temp+len;
}
fhand = fopen("foo.asm","wb");
GenerateFile(OFILE_LST,fhand,0,0x3d,0x1F);
fclose(fhand);
Wait();
Exit(0);
}
:f:\IDA_FRE_5\idag.exe -c -B -S.\foo.idc foo.dmp
:head -n 30 foo.asm | tail
seg000:00000000 ; Segment type: Pure code
seg000:00000000 seg000 segment byte public 'CODE' use32
seg000:00000000 assume cs:seg000
seg000:00000000 assume es:nothing, ss:nothing, ds:nothing, fs:no thing, gs:nothing
seg000:00000000 push 10h
seg000:00000002 push 7C80B730h
seg000:00000007 call near ptr 0FFFF6DE4h
seg000:0000000C and dword ptr [ebp-4], 0
with windbg you can get the disassembly right from command line like this
:cdb -c ".dvalloc /b 60000000 2000;.readmem foo.dmp 60001000 l?0n61;u 60001000 60001040;q" calc
0:000> cdb: Reading initial command '.dvalloc /b 60000000 2000;.readmem foo.dmp 60001000 l?0n61;u 60001000 60001040;q'
Allocated 2000 bytes starting at 60000000
Reading 3d bytes.
60001000 6a10 push 10h
60001002 6830b7807c push offset kernel32!`string'+0x88 (7c80b730)
60001007 e8d86dffff call 5fff7de4
6000100c 8365fc00 and dword ptr [ebp-4],0
60001010 64a118000000 mov eax,dword ptr fs:[00000018h]
60001016 8945e0 mov dword ptr [ebp-20h],eax
60001019 817810001e0000 cmp dword ptr [eax+10h],1E00h
60001020 750f jne 60001031
60001022 803d0850887c00 cmp byte ptr [kernel32!BaseRunningInServerProcess (7c885008)],0
60001029 7506 jne 60001031
6000102b ff15f812807c call dword ptr [kernel32!_imp__CsrNewThread (7c8012f8)]
60001031 ff750c push dword ptr [ebp+0Ch]
60001034 ff5508 call dword ptr [ebp+8]
60001037 50 push eax
60001038 e8c9090000 call 60001a06
6000103d 0000 add byte ptr [eax],al
6000103f 0000 add byte ptr [eax],al
quit:
ollydbg 1.10 view-> file-> (mask any file) -> foo.dmp -> rightclick -> disassemble

error: no multiboot header found

This day found something that caught my attention. is build a simple bare OS
i read how to make multiboot compliant, I'm using NASM and GCC, i need make a loader that has the multiboot header and call the main point of my system for that i have two files loader.asm and loader.ld
loader.asm
[BITS 32]
global start
start:
mov esp, _sys_stack
jmp stublet
ALIGN 4
mboot:
MBOOT_PAGE_ALIGN equ 1<<0
MBOOT_MEMORY_INFO equ 1<<1
MBOOT_HEADER_MAGIC equ 0x1BADB002
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEMORY_INFO
MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)
; This is the GRUB Multiboot header. A boot signature
dd MBOOT_HEADER_MAGIC
dd MBOOT_HEADER_FLAGS
dd MBOOT_CHECKSUM
stublet:
EXTERN cmain
call cmain
jmp $
SECTION .bss
resb 8192
_sys_stack:
loader.ld
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
main.c
int GenyKernel_Main()
{
char *str = "Hello world!", *ch;
unsigned short *vidmem = (unsigned short*) VIDEO_MEMORY;
unsigned i;
for (ch = str, i = 0; *ch; ch++, i++) {
vidmem[i] = (unsigned char) *ch | 0x0700;
}
return 0;
}
for build i'm using
# loader.o
nasm -f elf64 -o loader.o loader.asm
# main.o
gcc -fno-stack-protector -fno-builtin -nostdinc -O -g -Wall -I. -c -o main.o main.c
and the finally link
ld -T loader.ld -o kernel loader.o main.o
I've built a simple iso with grub-mkrescue and run with qemu but always I get
I think the problem is in the file loader.ld but i can't found where
After read lots about the same .asm file i finally understood the problem, the following snippet
align 4
multiboot_header:
dd MBOOT_MAGIC
dd MBOOT_FLAGS
dd MBOOT_CHECKSUM
must exist below a section to include appropriately with the linker
section .text ; .multiboot o whatever
align 4
multiboot_header:
dd MBOOT_MAGIC
dd MBOOT_FLAGS
dd MBOOT_CHECKSUM
and in the linker script
ENTRY(your_entry_point)
SECTIONS
{
. = 0x00100000;
.text ALIGN(0x1000) :
{
*(.multiboot)
*(.text)
}
// rest of sections
}