Wol*_*fer 5 c sockets linux assembly x86-64
大家好。
所以我正在学习汇编。
按照我通常学习的任何新语言的学习步骤,我已经到达了使用程序集的网络。
遗憾的是,情况不太好,因为我在第 0 步几乎失败了,这将获得一个可以开始通信的套接字。
汇编代码应大致等于以下 C 代码:
#include <stdio.h>
#include <sys/socket.h>
int main(){
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
}
Run Code Online (Sandbox Code Playgroud)
(让我们忽略它现在没有关闭套接字的事实。)
所以这是我到目前为止所做的:
在某些架构上——例如 x86-64 和 ARM——没有 socketcall() 系统调用;相反,socket(2)、accept(2)、bind(2) 等实际上是作为单独的系统调用实现的。
然而,在系统调用的原始列表中没有这样的调用——据我所知socket()
,accept()
、bind()
、listen()
、 等是来自libnet
而不是来自内核的调用。这让我很困惑,所以我决定编译上面的C
代码并使用strace
. 这产生了以下结果:
套接字(PF_INET,SOCK_STREAM,IPPROTO_IP)= 3
虽然这并没有让我更接近于知道它是什么socket()
,但它确实解释了它的论点。对于女巫,我似乎没有找到合适的文档(再次)。我认为PF_INET
,SOCK_STREAM
,IPPROTO_IP
就在被定义<sys/socket.h>
,但我grep
似乎对他们-ing没有发现使用的东西。所以我决定通过gdb
与disass main
查找值一起使用来实现它。这给出了以下输出:
汇编代码转储功能主要:0x00000000004004fd <0>:推RBP 0x00000000004004fe <1>:MOV RBP,RSP 0x0000000000400501 <4>:子RSP,为0x10 0x0000000000400505 <8>:MOV EDX,为0x0 0x000000000040050a <13 >:MOV ESI,为0x1 0x000000000040050f <18>:MOV EDI,0X2 0x0000000000400514 <23>:呼叫0x400400 0x0000000000400519 <28>:MOV DWORD PTR [RBP-为0x4],EAX 0x000000000040051c <31>:假
0x000000000040051d <+ 32>: ret
汇编程序转储结束。
根据我的经验,这意味着socket()
从EDX
( PF_INET
), ESI
(SOCK_STREAM
) 和EDI
( IPPROTO_IP
)。这将是奇怪的系统调用(如Linux的系统调用约定是使用EAX
/RAX
递增的顺序呼叫号码和其他寄存器的参数,如:RBX
,RCX
,RDX
...)。这是 beaing CALL
-ed 而不是INT 0x80
'd 的事实也意味着这实际上不是系统调用,而是从共享对象调用的东西。或者其他的东西。
但话又说回来。对于CALL
-ed 的东西,在寄存器中传递参数非常奇怪。通常,据我所知,被调用事物的参数应该被PUSH
放到堆栈上,因为编译器不知道它们会尝试使用哪些寄存器。
当使用以下命令检查生成的二进制文件时,这种行为变得更加奇怪ldd
:
linux-vdso.so.1 (0x00007fff4a7fc000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f56b0c61000) /lib64/ld-linux-x86-64.so.2001000007 )
似乎没有网络库的链接。
这就是我没有想法的地方。
所以我要求以下内容:
x86-64
linux 内核的实际系统调用及其相关编号的。(最好作为 . 的头文件C
)PF_INET
,SOCK_STREAM
,IPPROTO_IP
因为我无法在我自己的系统上找到它们,这让我很烦恼。x86-64
linux 上的程序集网络教程。(为了x86-32
很容易找到材料,但出于某种原因,我想出了 64 位的东西。)谢谢!