Assembly programs have 3 sections, right? Data, bss, and text. Data is used to store variables, bss is used to reserve space for variables, whereas text is where your command are located. Your programs work because the computer executes .text section, which might use .data section. Data section is not supposed to be run, but only used. Nonetheless, it is possible to run the code written in data section. Let’s take a look:

.section .data
code_to_exec:

.byte 0xeb, 0x1d, 0x5e, 0x31, 0xc0, 0x83, 0xc0, 0x04, 0x31, 0xdb
.byte 0x83, 0xc3, 0x02, 0x8d, 0x0e, 0x31, 0xd2, 0x83, 0xc2, 0x05
.byte 0xcd, 0x80, 0x31, 0xc0, 0x83, 0xc0, 0x01, 0x31, 0xdb, 0xcd
.byte 0x80, 0xe8, 0xde, 0xff, 0xff, 0xff, 0x6b, 0x65, 0x77, 0x6c
.byte 0x0a, 0x00

.section .text
.globl _start
_start:

call func
func: leal code_to_exec, %eax
movl %eax, (%esp)
ret

.ascii "This is an area for comments. This space will never be read."

Nice and simple. Only 4 commands in the data section. Let’s compile and run, and then I’ll explain how it works:

jon@localhost:~> as datasec.s -o datasec.o
jon@localhost:~> ld datasec.o -o datasec
jon@localhost:~> ./datasec
kewl
jon@localhost:~>

Alright, first command call func pushes address of the next code of line onto the stack. Then, we copy address of “code_to_exec” into register %eax. Now it gets interesting (as if you haven’t been excited already). The register %esp always points to the last value pushed onto the CPU stack. Right now it contains the address of the second line of code. So what we do is we substitute it with the address of “code_to_exec” string. movl %eax, (%esp) moves what’s in our register %eax into wherever %esp points (by dereferencing that register). All we need now is to make the computer jump to that address and start executing our “code_to_exec”, so we simply issue a ret command which pops the address off of the stack and jumps there.

Voila, the “code_to_exec” string is executed. What my string does is simply print the word “kewl” to the screen. I got those bytes by writing a program in assembly, then disassembling it with GDB, and putting them manually in this program. Of course, you don’t have to write your “code_to_exec” string in assembly. If you feel more comfortable with C, go for it.

So, that’s the basics behind executing data section of the assembly program under x86 processor running *nix.

Follow

Get every new post delivered to your Inbox.