From: Frank K. <fbk...@zy...> - 2010-12-20 21:00:10
|
Littlefield, Tyler wrote: > Rather than filling everyone's inbox replying to all of these, just > wanted to say thanks for all the help. Hi Tyler, You're welcome. I'm going to undo your consideration and fill up everybody's mailbox, though, 'cause I think your questions are interesting, and might lead to some discussion. If anyone thinks this list is generating too much traffic, they can complain... or just unsubscribe. :) > It helped. I have two more > questions. First, I'm working with Unix systems. How would I go about > creating a socket, closing the socket, etc? ASSuming you want to do this via the int 80h interface, there's really only one sys_socketcall (102). This is usually "wrapped" to socket (create), connect, bind, listen, etc. Even Konstantin's "asmutils" provides macros for sys_socket, etc. But the "real" interface is just sys_socketcall, with the subfunctions or "commands" in ebx - ecx points to remaining parameters. In order to not "hide" anything, I like to do it that way, although we're "supposed" to use the C library interface (they make me say that). There are "send" and "recv" commands, but sys_write/sys_read seem to work - sys_close seems to work - just like any other file descriptor. > Last, do we have some sort > of method for using malloc? I don't think it's an actual syscall, but I > need to be able to allocate memory. Well, "just call malloc". There are a couple of system calls that will get us a chunk of memory - sys_mmap (or mmap2?) and sys_brk. These get us a minimum of 4096 bytes. To "malloc" smaller pieces, we're on our own. I think Jonathan Bartlett's "PGU" has an example. I think sys_mmap gets us memory starting about 40000000h, sys_brk gives us memory contiguous with the end of our existing memory, which may be an advantage(?). As I recall, "man 2 brk" isn't too helpful (unusually). xor ebx, ebx mov eax, 45 int 80h ; check for error - shouldn't be any(?) mov [orig_break], eax mov ebx, eax add ebx, 4096 ; or some multiple mov eax, 45 int 80h ; check for error - might be out of memory Now eax should have our new "break" (where memory ends for our process). We can use memory between "orig_break" and "new_break". To "free" it: mov ebx, [orig_break] mov eax, 45 int 80h Now we should be back where we were. I think that works... Getting back to sockets, here's my adaptation of Scott Lanning's "daytime_cli.s" (available at Konstantin's linuxassembly.org, or http://asm.sf.net somewhere): ;----------------------------- ; daytime client in Linux asm, syscalls only ; loosely based on daytime_cli.s from Scott Lanning ; ; nasm -f elf32 daytime.asm ; ld -o daytime daytime.o global _start struc sockaddr_in .sin_family resw 1 .sin_port resw 1 .sin_addr resd 1 .sin_zero resb 8 endstruc _ip equ 0x7F000001 ; loopback - 127.0.0.1 _port equ 13 ; Convert numbers to network byte order IP equ ((_ip & 0xFF000000) >> 24) | ((_ip & 0x00FF0000) >> 8) | ((_ip & 0x0000FF00) << 8) | ((_ip & 0x000000FF) << 24) PORT equ ((_port >> 8) & 0xFF) | ((_port & 0xFF) << 8) AF_INET equ 2 SOCK_STREAM equ 1 BUFLEN equ 0x80 STDIN equ 0 STDOUT equ 1 __NR_exit equ 1 __NR_read equ 3 __NR_write equ 4 __NR_socketcall equ 102 SYS_SOCKET equ 1 SYS_CONNECT equ 3 section .data my_sa istruc sockaddr_in at sockaddr_in.sin_family, dw AF_INET at sockaddr_in.sin_port, dw PORT at sockaddr_in.sin_addr, dd IP at sockaddr_in.sin_zero, dd 0, 0 iend socket_args dd AF_INET, SOCK_STREAM, 0 ; first of these wants to be socket descriptor ; we fill it in later... connect_args dd 0, my_sa, sockaddr_in_size section .bss my_buf resb BUFLEN sock_desc resd 1 section .text _start: ; socket(AF_INET, SOCK_STREAM, 0) mov ecx, socket_args ; address of args structure mov ebx, SYS_SOCKET ; subfunction or "command" mov eax, __NR_socketcall ;c.f. /usr/src/linux/net/socket.c int 80h cmp eax, -4096 ja exit mov [sock_desc], eax ; and fill in connect_args mov [connect_args], eax ; connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr)) mov ecx, connect_args mov ebx, SYS_CONNECT ; subfunction or "command" mov eax, __NR_socketcall int 80h cmp eax, -4096 ja exit ; read(sock, buf, len) mov edx, BUFLEN ; arg 3: max count mov ecx, my_buf ; arg 2: buffer mov ebx, [sock_desc] ; arg 1: fd mov eax, __NR_read ; sys_read int 80h cmp eax, -4096 ja exit ; write(stdout, buf, len) mov edx, eax ; length read is length to write mov ecx, my_buf mov ebx, STDOUT mov eax, __NR_write int 80h xor eax, eax ; success exit: mov ebx, eax ; exitcode mov eax, __NR_exit int 80h ;---------------------- That probably won't do anything, unless you've already got a "daytime" server running. Edit (as root) /etc/inetd.conf and uncomment the "daytime" line. Do "ps x" to get the ID for inetd, and "kill -HUP xxxx". Works for me. If your system is different, enlighten me! I have a couple other examples... an "echo" (or echo-like) client and server (not a very good "server"). I also have a couple examples Nathan Baker sent me - Windows programs using the NASMX package. I've written a "fakeapi.asm" containing functions with the same names and parameters as the Windows APIs, that do "approximately" the same thing. Linking (statically) against this allows the same programs to run in Linux. This is just a novelty, and will *not* work in the "general case", but I thought it was amusing... If anyone wants to see any of these, give a yell. Best, Frank |