裸调linux write()接口

背景

我们知道linux提供了很多系统调用给应用程序使用,但linux并没有将这些系统调用封装成C语言接口,而是提供一个软中断,然后应用程序需要通过软中断带上系统调用编号和参数去调用接口,这对于应用程序相当的不友好。这时候libc库便登上了历史舞台,它将这些系统调用封装成一个个函数,形象生动地提供给应用程序使用,从此之后,应用程序只需要调用那些write(), read(), exit()等便能达到目的,而不是通过软中断去使用这些接口。。

然后,当我们熟悉了这些符号接口的时候,却不知道背后是怎么工作的,所以今天我们就来搞事情!我们将干掉LIBC,直接调用系统的接口,看看怎么通过软中断去调用这些接口。

代码

//#include <unistd.h>
char* str = "Hello World\n";

void print()
{
  asm( "movl $12,%%edx \n\t"
       "movl %0,%%ecx  \n\t"
       "movl $0,%%ebx  \n\t"
       "movl $4,%%eax  \n\t"
       "int $0x80      \n\t"
       ::"r"(str):"edx","ecx","ebx");
}

void main()
{
  //write(0, str, 12);
  print();
}

我们选择的write接口看起来很简单哦,哈哈

注意:这段代码只能在linux i386(32位)版本上编译运行,x64我还不知道怎么玩 :=(

分析

write函数原形如下:

ssize_t write (int fd, const void * buf, size_t count);

它有3个参数(文件句柄、写入缓冲区,写入字节数),这3个参数分别传递给ebx, ecx, edx寄存器。

我们来逐行看汇编代码:

movl $12,%%edx \n\t   

解析: 将数字12直接赋值给寄存器edx,12是字符串“Hello World\n”的长度。$符号可以直接引用数字,%%引用寄存器。 \n\t用于换行,如果汇编语句比较多,可以用它来换行。

movl %0,%%ecx  \n\t

解析: 这行的含义是将字符串指针赋值给ecx寄存器。%号是引用C语言输入的内容,%0表示第0个(最多9个)输入或输出的内容,这里就是str字符串。

movl $0,%%ebx  \n\t

解析:直接将0赋值给ebx寄存器,这里是write函数的第一个参数——文件句柄,0是标准输出。

movl $4,%%eax  \n\t

解析:这行是设置中断号,write系统调用的中断号是4,存储到eax寄存器中。

int $0x80      \n\t

解析:这行就简单啦,调用系统的软中断,搞定。

::"r"(str):"edx","ecx","ebx"

解析:最后一行费解一点!我们先来看下AT&T汇编语言的基本形式

 可以看出,一段汇编代码分为4个部分,每个部分之间用“:”隔开,如果中间那个部分没有语句,也必须用“:”隔开,但如果最后那部分没有语句,可以不用增加“:”

  • instruction(指令).每条指令之后最好使用"\n\t"结尾,这样在gcc产生汇编格式比较好
  • output operand(输出操作数),每个输出部分使用,分隔."="作为修饰符,"m"表示存放位置/约束符,()里面表示对应C程序值。
  • input operand(输入操作数),这个部分和输出是一样的。
  • clobber(不知道怎么翻译),这个部分是告诉gcc在这条指令里面我们会修改什么值。

套用这套形式,可以看出,第一个“:”前也就是int $0x80 及之前的语句是指令;

第二个“:”和第一个“:”之间是空的,说明我们的输出操作数是空的;

第三个“:”和第二个“:”之间是输入操作数,这里我们将str指针作为参数输入给了“r”寄存器,在指令中我们可以通过%0~%9来引用输出/输入的值。输入/输出按从左到右,从上到下的规则匹配0~9;我们在前面的指令中使用%0引用了str指针,并把它的值赋给了ecx寄存器。

第三个“:”之后告诉gcc我们修改了什么,这里我们修改了ebx,ecx,edx寄存器

具体的汇编语法请参考下面的链接!到此我们应该理解透了write系统调用怎么调了,所以我们是不是可以翻一下LIBC的其他函数,再搞搞事情,哈哈~

参考资料

AT&T汇编语言语法:GCC内嵌汇编 (dirtysalt.github.io)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值