Error[8]: Undefined offset: 12, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

背景

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

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

代码
//#include 
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 ,%%edx \n\t   

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

movl %0,%%ecx  \n\t

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

movl movl ,%%eax  \n\t,%%ebx  \n\t

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

int ::"r"(str):"edx","ecx","ebx"x80      \n\t

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

  • instruction(指令).每条指令之后最好使用"\n\t"结尾,这样在gcc产生汇编格式比较好
  • 解析:这行就简单啦,调用系统的软中断,搞定。

  • output operand(输出 *** 作数),每个输出部分使用,分隔."="作为修饰符,"m"表示存放位置/约束符,()里面表示对应C程序值。
  • 解析:最后一行费解一点!我们先来看下AT&T汇编语言的基本形式

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

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

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

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

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

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

    参考资料

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

    )
    File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
    File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
    File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
    Error[8]: Undefined offset: 13, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
    File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

    背景

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

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

    代码
    //#include 
    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 ,%%edx \n\t   

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

    movl %0,%%ecx  \n\t

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

    movl movl ,%%eax  \n\t,%%ebx  \n\t

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

    int ::"r"(str):"edx","ecx","ebx"x80      \n\t

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

  • instruction(指令).每条指令之后最好使用"\n\t"结尾,这样在gcc产生汇编格式比较好
  • 解析:这行就简单啦,调用系统的软中断,搞定。

  • output operand(输出 *** 作数),每个输出部分使用,分隔."="作为修饰符,"m"表示存放位置/约束符,()里面表示对应C程序值。
  • 解析:最后一行费解一点!我们先来看下AT&T汇编语言的基本形式

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

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

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

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

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

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

    参考资料

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

    )
    File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
    File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
    File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
    裸调linux write_C_内存溢出

    裸调linux write

    裸调linux write,第1张

    背景

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

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

    代码
    //#include 
    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 ,%%edx \n\t   

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

    movl %0,%%ecx  \n\t

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

    movl movl ,%%eax  \n\t,%%ebx  \n\t

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

    int ::"r"(str):"edx","ecx","ebx"x80      \n\t

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

  • instruction(指令).每条指令之后最好使用"\n\t"结尾,这样在gcc产生汇编格式比较好
  • 解析:这行就简单啦,调用系统的软中断,搞定。

  • output operand(输出 *** 作数),每个输出部分使用,分隔."="作为修饰符,"m"表示存放位置/约束符,()里面表示对应C程序值。
  • 解析:最后一行费解一点!我们先来看下AT&T汇编语言的基本形式

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

    • 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)

    欢迎分享,转载请注明来源:内存溢出

    原文地址: https://outofmemory.cn/langs/793881.html

    (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-05-06
    下一篇 2022-05-06

    发表评论

    登录后才能评论

    评论列表(0条)

    保存