当前位置: 首页 > news >正文

做网站还有希望吗app制作公司

做网站还有希望吗,app制作公司,网页设计工资怎么算,《建设工程质量管理条例》有时候,我们希望修改Linux的内核某些行为,或者更一般的,我们需要进行一些统计,比如说我们希望实时统计出当前系统的TCP半连接数量。 但问题是,可能没有现成的工具可以使用,也不能重新编译内核,…

有时候,我们希望修改Linux的内核某些行为,或者更一般的,我们需要进行一些统计,比如说我们希望实时统计出当前系统的TCP半连接数量。

但问题是,可能没有现成的工具可以使用,也不能重新编译内核,那么怎么办呢?

kpatch机制就是干这个的。

你可能认为我接下来要开始介绍kpatch的原理和用法了。但并不是,我不善于为工具写文档介绍用法,我更擅长手艺人的做法。下面的篇幅,正式开始展示一个不使用kpatch技术来实现等效功能的方法。

我以一个demo开始介绍其原理,下一篇文章我将介绍一个正式的可以使用的例子。如果有一些细节上的疑问,建议在我前两天写的文章中试着找找答案,如果还有问题需要解决,直接email我或者wechat我都可以。

我前面的文章链接如下:
https://blog.csdn.net/dog250/article/details/105135219
https://blog.csdn.net/dog250/article/details/105129254
https://blog.csdn.net/dog250/article/details/105093969

好了,让我们直接上demo模块代码:

#include <linux/module.h>
#include <linux/proc_fs.h>static ssize_t sample_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
{int n = 0;char kb[16];if (*ppos != 0) {return 0;}n = sprintf(kb, "%d\n", 1234);memcpy(ubuf, kb, n);*ppos += n;return n;
}static struct file_operations sample_ops = {.owner = THIS_MODULE,.read = sample_read,
};static struct proc_dir_entry *ent;
static int __init sample_init(void)
{ent = proc_create("test", 0660, NULL, &sample_ops);if (!ent)return -1;return 0;
}static void __exit sample_exit(void)
{proc_remove(ent);
}module_init(sample_init);
module_exit(sample_exit);
MODULE_LICENSE("GPL");

该模块会在procfs文件系统中创建/proc/test这个文件,我的目标是,每次读取这个文件的时候,另一个内核模块中的一个计数器counter这个值递增1.

由于模块已经写好了,我们不可能去修改它,这就是展示手艺的点了,我们从外部在另一个模块里来增加计数器递增的操作。

为了hook住sample_read这个函数,我们先看它的反汇编:

crash> dis sample_read
0xffffffffa00e1000 <sample_read>:       nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffffa00e1005 <sample_read+5>:     push   %rbp
0xffffffffa00e1006 <sample_read+6>:     mov    %rsp,%rbp
0xffffffffa00e1009 <sample_read+9>:     push   %r13
0xffffffffa00e100b <sample_read+11>:    push   %r12
0xffffffffa00e100d <sample_read+13>:    push   %rbx
0xffffffffa00e100e <sample_read+14>:    mov    %rcx,%rbx
0xffffffffa00e1011 <sample_read+17>:    sub    $0x18,%rsp
0xffffffffa00e1015 <sample_read+21>:    mov    %gs:0x28,%rax
0xffffffffa00e101e <sample_read+30>:    mov    %rax,-0x20(%rbp)
0xffffffffa00e1022 <sample_read+34>:    xor    %eax,%eax
// 下面是if (*ppos != 0) 判断语句
0xffffffffa00e1024 <sample_read+36>:    cmpq   $0x0,(%rcx)
0xffffffffa00e1028 <sample_read+40>:    jne    0xffffffffa00e105a <sample_read+90>
// 下面的两行就是HOOK点!!!
0xffffffffa00e102a <sample_read+42>:    lea    -0x30(%rbp),%rdi
0xffffffffa00e102e <sample_read+46>:    mov    %rsi,%r13
0xffffffffa00e1031 <sample_read+49>:    mov    $0x4d2,%edx
0xffffffffa00e1036 <sample_read+54>:    mov    $0xffffffffa00e2024,%rsi
0xffffffffa00e103d <sample_read+61>:    callq  0xffffffff812fd960 <sprintf>

我们只需要将lea和后面mov两行替换成一个jmp/call到自己定义的地址就可以了,同时把lea/mov移到自定义的逻辑里面去执行,执行完成后,在jmp/ret回来。

本例中,为了避免jmp过去后再jmp回来,所以使用call,因为ret可以自动jmp回来。

非常简单的逻辑,直接上代码吧:

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/cpu.h>char *stub;
char *addr = NULL;// laddr 参数保存sample_read的地址,通过/proc/kallsyms查询后传入
static unsigned long laddr = 0xffffffffa0267000;
module_param(laddr, ulong, 0644);// 独立的计数器,每次读取/proc/test时,该计数器加1
static unsigned int counter = 0;
module_param(counter, int, 0444);void test_stub1(void) __attribute__ ((aligned (1024)));
void test_stub2(void) __attribute__ ((aligned (1024)));
void test_stub1(void)
{printk("yes\n");
}
void test_stub2(void)
{printk("yes yes\n");
}#define POKE_OFFSET		42 // sample_read的42偏移处需要被poke成jmp
#define POKE_LENGTH		7  // 被poke的必须是完整的指令行,如果有空余的,用nop填充// text_poke和text_mutex通过/proc/kallsyms查询地址
static void *(*_text_poke_smp)(void *addr, const void *opcode, size_t len);
static struct mutex *_text_mutex;static int __init hotfix_init(void)
{unsigned char e8_call[POKE_LENGTH];unsigned char incl[8];s32 offset;u32 low32 = (unsigned int)(((unsigned long)&counter) & 0xffffffff);addr = (void *)laddr;_text_poke_smp = (void *)0xffffffff8163e1f0;_text_mutex = (void *)0xffffffff81984920;stub = (void *)test_stub1;offset = (s32)((long)stub - (long)addr - 5);// 插入的指令中需要save/restore寄存器,但这里简单,略过incl[0] = 0xff;incl[1] = 0x04;incl[2] = 0x25;(*(u32 *)(&incl[3])) = low32; // 写入需要递增的counter变量地址incl[7] = 0xc3; // retq 指令// 执行poke:1. 首先拷贝原始函数中的指令; 2. 其次写入新增的计数器递增指令 _text_poke_smp(&stub[0], &addr[POKE_OFFSET], POKE_LENGTH);_text_poke_smp(&stub[POKE_LENGTH], &incl, 8);// call比jmp方便,可以自动帮忙return,不然还要自己jmp回来,但是代价是push/pope8_call[0] = 0xe8;(*(s32 *)(&e8_call[1])) = offset - POKE_OFFSET;e8_call[5] = 0x90; e8_call[6] = 0x90; // nop 占位符get_online_cpus();mutex_lock(_text_mutex);// 执行call指令替换_text_poke_smp(&addr[POKE_OFFSET], e8_call, POKE_LENGTH);mutex_unlock(_text_mutex);put_online_cpus();return 0;
}static void __exit hotfix_exit(void)
{get_online_cpus();mutex_lock(_text_mutex);_text_poke_smp(&addr[POKE_OFFSET], &stub[0], POKE_LENGTH);mutex_unlock(_text_mutex);put_online_cpus();
}module_init(hotfix_init);
module_exit(hotfix_exit);
MODULE_LICENSE("GPL");

我们看下效果:

[root@localhost ~]# cat /proc/test
1234
[root@localhost ~]# cat /sys/module/nowa/parameters/counter
1
[root@localhost ~]# cat /proc/test
1234
[root@localhost ~]# cat /sys/module/nowa/parameters/counter
2
[root@localhost ~]# cat /proc/test
1234
[root@localhost ~]# cat /sys/module/nowa/parameters/counter
3

已经实现效果了。我们看一下原始的sample_read和test_stub1变成了什么样子:

crash> dis sample_read
...
0xffffffffa00e1024 <sample_read+36>:    cmpq   $0x0,(%rcx)
0xffffffffa00e1028 <sample_read+40>:    jne    0xffffffffa00e105a <sample_read+90>
// 注意下面的7个字节的指令,已经被替换了
0xffffffffa00e102a <sample_read+42>:    callq  0xffffffffa0264000 <test_stub1>
0xffffffffa00e102f <sample_read+47>:    nop
0xffffffffa00e1030 <sample_read+48>:    nop
0xffffffffa00e1031 <sample_read+49>:    mov    $0x4d2,%edx
...
crash> dis test_stub1
// 下面的7字节指令拷贝自原始函数
0xffffffffa0264000 <test_stub1>:        lea    -0x30(%rbp),%rdi
0xffffffffa0264004 <test_stub1+4>:      mov    %rsi,%r13
// 计数器递增指令
0xffffffffa0264007 <test_stub1+7>:      incl   0xffffffffa0266278
0xffffffffa026400e <test_stub1+14>:     retq
...

浙江温州皮鞋湿,下雨进水不会胖。

http://www.lbrq.cn/news/2653885.html

相关文章:

  • 网站推广积分一键注册所有网站
  • wordpress导入网站文章优化品牌seo关键词
  • 越秀网站建设价格怎么样免费做网站
  • 做一些网站犯法么google应用商店
  • seo chinazseo排名哪家正规
  • H5平台网站建设运营seo是什么意思
  • 网络下载的网站模板能直接上传到虚拟主机优化大师官网登录入口
  • 织梦网站上传新闻免费做推广的网站
  • wordpress 试用济南seo排名搜索
  • 网店运营教学排名优化工具下载
  • 做网站应该学什么语言今日油价92汽油价格
  • 中国铁道建筑集团有限公司seo资源咨询
  • dz论坛如何做网站地图网站seo的内容是什么
  • dw做网站小技巧建站推广
  • 厦门网站推广费用百度广告推广收费标准
  • 为什么教育网站做的都很烂seo整站优化哪家好
  • 贸易做网站百度灰色词排名代发
  • 教育网站开发公司百度最怕哪个投诉电话
  • 竞争者网站建设情况seo的作用是什么
  • php学什么可以做网站百度录入网站
  • 株洲做网站的公司公司网站制作
  • 关于设计网站seo点击优化
  • wordpress更好后台登录logo优化落实防控措施
  • 重庆品牌网站建设公司排名免费的发帖收录网站
  • 广州目前有疫情吗河南seo优化
  • 京伦科技做的网站如何球队排名世界
  • 网站建设 资产国际重大新闻事件2023
  • 网站策划书撰写流程厦门网
  • 集团网站建设的好处品牌推广策略有哪几种
  • 网站怎么做营销策划龙华线上推广
  • CentOS7编译安装GCC
  • Javaweb - 14.1 - 前端工程化
  • FreeRTOS入门知识(初识RTOS)(一)
  • Git 基础操作笔记(速查)
  • 力扣-238.除自身以外数组的乘积
  • WORD接受修订,并修改修订后文字的颜色