How to use use as in linux with assembly language - linux

I am studying Linux kernel, so I have to read some assembly code. Here is a sample code
SYSWRITE=4
.globl mywrite,myadd
.text
mywrite:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl 8(%ebp),%ebx
movl 12(%ebp),%ecx
movl 16(%ebp),%edx
movl $SYSWRITE,%eax
int $0x80
popl %ebx
movl %ebp,%esp
popl %ebp
ret
myadd:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl 12(%ebp),%edx
xorl %ecx,%ecx
addl %eax,%edx
jo 1f
movl 16(%ebp),%eax
movl %edx,(%eax)
incl %ecx
1:
movl %ecx,%eax
movl %ebp,%esp
popl %ebp
ret
I use the as in this way
"as -o callee.o callee.s"
to compile it,but it fails with a message saying something like this
"callee.s|5| Error: suffix or operands invalid for `push'"

You're probably on a 64-bit machine, so your as defaults to 64-bit. Since you have 32-bit code, you want to use:
as -32 -o callee.o callee.s

Related

Scanf a char pointer in Assembly

So I have a task to do, which requires from me to scanf a char* in assembly. I tried this code:
.data
INPUT_STRING: .string "Give me a string: "
SCANF_STRING: .string "%s"
PRINTF_STRING: .string "String: %s\n"
.text
.globl main
.type main, #function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $32, %esp
pushl $INPUT_STRING
call printf #printf("Give me a string: ")
addl $4, %esp
pushl -12(%ebp) # char*
pushl $SCANF_STRING # "%s"
call scanf scanf("%s", char*)
addl $8, %esp
pushl -12(%ebp)
pushl PRINTF_STRING
call printf #printf("String: %s\n")
addl $16, %esp
movl -4(%ebp), %ecx
xorl %eax, %eax
leave
leal -4(%ecx), %esp
ret
It writes down first printf correctly, then it waits for input (so scanf works), but then when I enter anything -> Segmentation fault.
I know, that the char* should be somehow initialized, but how can I do it from the assembly level?
I am compiling it on Manjaro 64 bit, with gcc -m32
GCC's stack-alignment code on entry to main is over-complicated:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $32, %esp
...
leave
leal -4(%ecx), %esp
ret
Do it so:
pushl %ebp
movl %esp, %ebp
subl $32, %esp # Space for 32 local bytes
andl $-16, %esp # Alignment by 16
...
leave
ret
The version of the i386 System V ABI used on modern Linux does guarantee/require 16-byte stack alignment before a call, so you could have re-aligned with 3 pushes (including the push %ebp) instead of an and. Unlike x86-64, most i386 library functions don't get compiled to use movaps or movdqa 16-byte aligned load/store on locals in their stack space, so you can often get away with unaligning the stack like you're doing with PUSHes before scanf. (ESP % 16 == 0 when you call printf the first time, though; that's correct.)
You want to use 12 bytes of the local stack frame for the string. scanf needs the start address of those 12 bytes. The address for that area isn't known at compile time. A -12(%ebp) gives you the value at this address, not the address itself. LEA is the instruction to calculate an address. So you have to insert this instruction to get the address at run time and to pass it to the C function:
leal -12(%ebp), %eax
pushl %eax # char*
And this is the working example (minor mistakes also corrected):
.data
INPUT_STRING: .string "Give me a string: "
SCANF_STRING: .string "%11s" ##### Accept only 11 characters (-1 because terminating null)
PRINTF_STRING: .string "String: %s\n"
.text
.globl main
.type main, #function
main:
pushl %ebp
movl %esp, %ebp
subl $32, %esp
mov $32, %ecx
mov %esp, %edi
mov $88, %al
rep stosb
pushl $INPUT_STRING
call printf # printf("Give me a string: ")
addl $4, %esp
leal -12(%ebp), %eax
pushl %eax # char*
pushl $SCANF_STRING # "%s"
call scanf # scanf("%s", char*)
addl $8, %esp
leal -12(%ebp), %eax
pushl %eax # char*
pushl $PRINTF_STRING ##### '$' was missing
call printf # printf("String: %s\n")
addl $8, %esp ##### 16 was wrong. Only 2 DWORD à 4 bytes were pushed
leave
ret

Sending an HTTP request and receiving output. x86 Linux assembly

I've been working on getting this assembly code to work for hours now. I've searched every possible article I could find.
.section .text
.global _start
_start:
push $0x66
popl %eax
cdq
pushl $0x1
popl %ebx
pushl %edx
pushl %ebx
pushl $0x2
movl %esp, %ecx
int $0x80
popl %ebx
popl %esi
pushl $0xdeadbeef # replace with inet_addr() result
movl $0xaffffffd, %ebp # ~(0080|AF_INET)
not %ebp
pushl %ebp
incl %ebx
pushl $0x10
pushl %ecx
pushl %eax
movb $0x66, %al
movl %esp, %ecx
int $0x80
popl %edi
_open_file:
movb $0x8, %al
pushl %edx
pushl $0x41
movl %esp, %ebx
pushl %eax
popl %ecx
int $0x80
xchg %eax, %esi
xchg %ebx, %edi
_gen_http_request:
#
# < use gen_httpreq.c, to generate a HTTP GET request. >
#
_gen_http_eof:
movb $0x4, %al
_send_http_request:
movl %esp, %ecx
int $0x80
cdq
incl %edx
_wait_for_dbl_crlf:
decl %ecx
movb $0x3, %al
int $0x80
cmpl $0x0d0a0d0a, (%ecx)
jne _wait_for_dbl_crlf
_pre_dump_loop:
movb $0x4, %dl
_dump_loop_do_read:
movb $0x3, %al
clc
_dump_loop_do_write:
int $0x80
xchg %ebx, %esi
jc _dump_loop_do_read
test %eax, %eax
jz _close_file
movb $0x4, %al
stc
jmp _dump_loop_do_write
_close_file:
movb $0x6, %al
int $0x80
_execve_file:
cdq
movb $0xb, %al
movl %edi, %ebx
pushl %edx
pushl %ebx
jmp _send_http_request
I've used the gen_httpreq.c to generate the HTTP request sent to the server.
My issue seems to be that the socket is never established. I watch the netstat output and when I execute the code above I don't get any connections at all. I'm curious if there's a specific way to do this.
Also, I've tried running netcat and listening on port 80 in another shell just to see if netstat wasn't picking up the connection, but nothing ever came through.
Here is my HTTP request.
pushl $0x0d0a0d0a
pushl $0x2f312e30
pushl $0x48545450
pushl $0x696c6520
pushl $0x2f2f2f66
pushl $0x47455420
When I execute it under strace, I get:
execve("./ht", ["./ht"], [/* 19 vars */]) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(8081), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
write(3, "", 0) = 0
read(3, 0xffc59c8c, 1) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
It just hangs and seems to do nothing at all.
If there is another way to download the file like this, for example, sending the HTTP request and then reading the output from that request.
So essentially I would do:
./download > newfile
I couldn't find anything else about this topic as it's pretty minimal.
Thanks for any help!
I have figured out what the issue was. When you use the program to generate the HTTP request, it returns all of the pushl's, but not the necessary movb at the end.
I added movb $0x14,%dl and it worked perfectly

Factorial Assembly x86

I have this assembly code(Linux 32Bit compiled with gcc -m32) and I do not really understand why my program doesn't work.
.data
.bla:
.ascii "%d\n\0"
.globl main
.text
main: pushl $4
call factorial
movl $1, %eax
ret
factorial:
push %ebp
movl %esp, %ebp
movl 8(%ebp), %ecx
cmpl $1, %ecx
jg .rek
movl $1, %eax
movl %ebp, %esp
pop %ebp
ret
.rek:
decl %ecx
pushl %ecx
call factorial
addl $4, %esp
movl 8(%ebp), %ecx
imull %ecx, %eax
pushl %eax
pushl $.bla
call printf
addl $8, %esp
movl %ebp, %esp
pop %ebp
ret
Unfortunately every time a Segmentation Fault does occur + parameters bigger than 4 do not work.
This should be my stack when I run the program with "3":
3
ret add
ebp
2
ret add
ebp
1
ret add
ebp
When I reach the bottom of the recursion I take the return value saved in eax and multiply it with 8(%ebp) which should be the next value.
I really appreciate any help you can provide.
Three issues I see.
1) Your call maine (I'm assuming that was a typo, and you meant, main) should be call factorial
2) In your main program, you don't restore your stack pointer.
3) Your printf call modifies %eax and overwrites the result of your factorial before it returns.
Repaired program:
.data
.bla:
.ascii "%d\n\0"
.globl main
.text
main: pushl $5
call factorial
addl $4, %esp # ADDED THIS
movl $1, %eax
ret
factorial:
push %ebp
movl %esp, %ebp
movl 8(%ebp), %ecx
cmpl $1, %ecx
jg .rek
movl $1, %eax
movl %ebp, %esp
pop %ebp
ret
.rek:
decl %ecx
pushl %ecx
call factorial # FIXED THIS
addl $4, %esp
movl 8(%ebp), %ecx
imull %ecx, %eax
pushl %eax # ADDED THIS - SAVE RETURN VALUE
pushl %eax
pushl $.bla
call printf
addl $8, %esp # MODIFIED THIS
pop %eax # ADDED THIS (restore eax result)
movl %ebp, %esp
pop %ebp
ret

Cannot access memory at address 0x ffffdfc4

I have assembly language progamme,but it show error
“Program received signal SIGSEGV,Segentation fault”
Why?the program is below:
.code32
.section .data
.section .text
.globl _start
_start:
pushl $3
pushl $2
call power
addl $8, %esp
pushl %eax
pushl $2
pushl $5
call power
addl $8, %esp
popl %ebx
addl %eax, %ebx
movl $1, %eax
int $0x80
.type power,#function
power:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
movl %ebx, -4(%ebp)
power_loop_start:
cmpl $1, %ecx
je power_loop_end
movl -4(%ebp), %eax
imull %ebx, %eax
movl %eax, -4(%ebp)
decl %ecx
jmp power_loop_start
power_loop_end:
movl -4(%ebp), %eax
movl %ebp, %esp
popl %ebp
ret
After compilation to run the program,it show segmentation fault (core dump) and gdb says:
Program received signal SIGSEGV,Segregation fault.
Why and how I fix it?
My problem is that I use 64 to compile 32 bit program.And I add some compiler
options to solve it.Such as bellow:
as -32 power.s -o power.o
ld -m elf_i386 power.o -o power
./power

Segmentation fault cmovl

I get the error 'Segmentation fault (core dumped)' when trying to run some compiled assembly. The code that makes the program crash is the following:
.global tiny
.type tiny, #function
tiny:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
# Compiling A1MINUS
movl $3, %eax
negl %eax
movl %eax, -4(%ebp)
# Compiling A0
movl -4(%ebp), %eax
movl %eax, -8(%ebp)
# Compiling A0
movl $7, %eax
movl %eax, -12(%ebp)
movl -8(%ebp), %eax
cmp %eax, -12(%ebp) // Error
movl $1, %eax // Error
movl %eax, %ebx //Error
movl $0, %eax //Error
cmovl %eax, %ebx // Error
movl %eax, -16(%ebp) // Error
# IF
movl -16(%ebp), %eax
cmp %eax , 0
jz lbl_3
movl -8(%ebp), %eax
pushl %eax
call print_int
addl $4, %esp
jmp lbl_4
lbl_3:
movl -12(%ebp), %eax
pushl %eax
call print_int
addl $4, %esp
lbl_4:
movl %ebp, %esp
popl %ebp
ret
I have no clue what my mistake is, any help is appreciated.
The wrong code (cmovl) is supposed to place a 0 or 1 in -16(%ebp), depending on the result of the comparison done by cmp. (the broken code is a translation of a 'lower then' statement).
As said in the comments, cmovl appearently can't make the code crash. Now I am even more clueless.
I am pretty sure the line cmp %eax, 0 causes the crash, because in at&t syntax the 0 there is a memory reference, a NULL pointer. Presumably you wanted to compare eax to 0, in which case you need cmp $0, %eax.
Learn to use a debugger.

Resources