首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

用Rust实现Brainfuck的JIT编译器

不同的 CPU 支持不同的指令集,目前我使用 Intel 的 64 位 CPU。同时我也将使用 NASM 语法。...正如我们在 Wikipedia 中可以看到的: 中央处理器(CPU)是计算机中的硬件,它通过执行系统的基本算术,逻辑和输入/输出操作来执行计算机程序的指令。 好的,CPU 会执行一些运算。...rax:临时寄存器,当我们调用 syscall 时,rax 必须包含 syscall 号码,所以后面的数字就是 syscall 的号码 rdi:用于将第 1 个参数传递给函数 rsi:用于将第 2 个参数传递给函数...rdx:用于将第 3 个参数传递给函数 换句话说,我们只是在调用 sys_write 的 syscall。...对于 stdin,stdout 和 stderr 来说,其值分别为 0,1 和 2 buf:指向字符数组 count:指定要写入的字节数 我们将 1 写入 rax,这意味我们要调用 sys_write。

88910

从Go编程看IO多路复用Select

,监控文件描述符集的读变化,如文件描述符集中有文件可读即通过该参数回传有变化的描述符,清空无变化的描述符;   w(writefds): 写监控文件描述符集,监控文件描述符集的写变化,如文件描述符集中有文件可写即通过该参数回传有变化的描述符...,清空无变化的描述符;   e(exceptfds): 异常监控文件描述符集,监控文件描述符集的异常,如文件描述符集中有文件异常即通过该参数回传有变化的描述符,清空无变化的描述符;   timeout参数...,该时间内未有状态变化时   大于0 有满足读、写、异常的文件描述符,需检查文件描述符集 特别关注   每次函数返回时都会将文件描述符集FdSet中未发生任何事件的fd清空,每次调用select时都需将所关注的...fd重新加入FdSet中;   可监控文件描述符个数取决于 FdSet中Bits的位长度,每个bit代表一个文件描述符,默认情况下Go中的定义为:Bits [16]int64,也就是一个8字节整数数组,...数组长度为16,第一个数组元素可存储的文件描述符为:0-63,第二个为:64-127依次类推;此时最多可以监听的文件描述符数为1024个; Select的相关问题:   1、内核将消息传递到用户空间需要执行系统拷贝

74050
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Linux下Shellcode编写

    012stdinstdoutstderr标准输入标准输出标准错误 第二个参数是字符串的指针,第三个参数是输出的字数,而 64 位的程序,寄存器传参:rdi, rsi, rdx, rcx, r8, r9...的差值,从而获得 hello_world 在内存中的位置 global _start section .text _start: jmp code hello_world:db 'hello world...写个shell 学会了这些基本的消除 bad character 的方法之后来写个真正的 shellcode 试试, 一个可以获得 shell 的 C 语言代码如下 char *const argv[]...rax 作为截断 push rdi mov rsi,rsp 以及系统调用号是 59,最后加一个 syscall add rax,59 syscall 把提取的 shellcode 放到之前的代码中编译~...[] = {"sh",NULL, NULL}; execve("/bin/sh", argv, NULL); return 0; } 接下来使用 syscall 依次实现这个程序,查找 socket

    2.3K31

    42.Linux应用调试-初步制作系统调用(用户态->内核态)

    table pointer // tbl等于数组表基地址 ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing...时,异或后,scno则等于0,表示数组表的基地址(第一个函数位置) ... ......, scno:要调用的sys_write()的索引值 lsl #2:左移2位,一个函数指针占据4个字节 从上面代码可以看出,2440的val基值为0x900000,也就是说要调用数组表的第一个函数时...,则使用: swi #0x900000 2 接下来,我们便来自制一个系统调用 1)在内核中,仿照一个sys_hello函数,然后放入数组表,供swi调用 2)写应用程序,直接通过swi指令,来调用sys_hello...,传递给内核的sys_hello() 5.重新烧写内核,试验应用程序 如上图所示,一个简单的系统调用便OK了 调用成功后,就可以来修改sys_hello(),来打印应用程序的各个寄存器值,打断点,来实现调试应用程序

    1.6K50

    38.Linux应用调试-初步制作系统调用(用户态->内核态)

    table pointer // tbl等于数组表基地址 ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing...时,异或后,scno则等于0,表示数组表的基地址(第一个函数位置) ... ......,则使用: swi #0x900000 2 接下来,我们便来自制一个系统调用   1)在内核中,仿照一个sys_hello函数,然后放入数组表,供swi调用   2)写应用程序,直接通过swi指令,...损坏部   和输入输出类似,一般用来处理操作的中间过程,因为这些原有的内容都会被损坏,比如上面的hello()里的"r0", “r1”,只是用来当做参数,传递给内核的sys_hello() 5.重新烧写内核...如上图所示,一个简单的系统调用便OK了   调用成功后,就可以来修改sys_hello(),来打印应用程序的各个寄存器值,打断点,来实现调试应用程序,需要用到: task_pt_regs(current

    98630

    进程控制第二弹(进程程序替换)

    调用exec并不创建新进程,所以调用exec前后该进程的id并未改变 我们知道,进程=内核数据结构+代码数据 程序替换的本质是将当前进程的代码和数据进行替换。 替换的时候,会不会创建新的进程?...所以为什么上述现象中,原来的进程中printf("testexec end! ...\n"); 没有执行的原因是,调用execl函数后,去执行ls程序了,原来的代码和数据被替换了。...在代码中,子进程执行一个新的程序execl("/usr/bin/ls","ls","-l","-a",NULL);此时有一个ls程序需要从磁盘中加载到物理内存中。...虽然代码是可读的,但是在操作系统看来都无所谓。所以重新开辟内存,将ls代码加载到物理内存,修改子进程的映射关系。至此,只要程序替换成功,彻底将子进程和父进程分开了。...老的环境变量稍作修改,传递给子进程 总结

    8710

    c语言printf、sprintf、vsprintf用法和区别

    格式化用法与 printf一致,相当于把 printf输出的内容放入指定数组中    vsprintf  #include #include void myPrintf...从而精简 sprintf需要先创建数组再传入参数的操作。          vsprintf 与 sprintf 功能相似,都是将格式化内容输出到指定数组。...有趣的来了,这tm输出的完全不对啊,我输入的明明是30和20,输出的是20和2125550836。  所以 sprintf 不适用于这种封装的传参,sprintf不能以不确定传参的方式来格式参数。 ...而 va_start(ap,fmt) 从实现方式来讲,它使va_list类型变量ap指向被传递给函数的可变参数表中的第一个参数,然后在栈中浏览参数,最后由于va_end(ap)释放掉ap。 ...最后总结:对于传参中参数类型和个数不确定的格式转换,请使用 vsprintf。

    3K40

    【Linux】详谈命令行参数&&环境变量

    main函数的第一个参数为argc,参数类型为int,第二个参数为argv,参数类型为char*类型的指针数组(也叫命令行参数表),该指针数组以NULL结尾。...当我们在命令行解释器输入一串指令时,命令行解释器会将这一串指令当成一个字符串,并以空格作为分隔符,将这个字符串分割成更小的字符串,并将这些更小的字符串分别存到argv数组中。...当你从命令行运行一个程序时,命令行解释器会负责解析命令行中的各个部分,包括程序名(即argv[0])和传递给程序的任何选项(即argv[1]、argv[2]等)。...解释器还会计算选项的数量,并将其作为argc的值传递给main函数。命令行解释器会负责将这些信息正确地传递给程序的main函数,以便程序能够使用它们。...[i]); 9 } 10 return 0; 11 } 有了命令行参数表,我们就可以通过在命令行中传不同的选项,让我们的同一个程序执行它内部不同的功能。

    41710

    Linux:进程替换

    execv:v结尾,其实就是vector(我们要先创建一个数组然后将参数放进去之后再整体传过去),有一点点像main函数的参数argv[]  execvp:就是vector+path  execle/execvpe...加载器的理解: argv这个参数会被传递给ls,其实exec系列接口含义也是如此,在命令行参数中,有所的进程都是bash的子进程,所以exec其实就是一个代码级别的加载器,他可以做到将可执行程序的代码和数据导入到内存中...,然后再调用main函数的时候将argc参数传递给程序,其实就相当于是你在执行该程序之前,优先给你加载出来一个栈帧结构。...(1)任何语言都有像exec这类的接口 (2)语言可以互相调用的原因是 无论是什么语言写的程序 在操作系统看来都是进程 1.5.3 将命令行参数和环境变量传递给另一个程序  环境变量是在子进程创建的时候就默认继承了...,所以表里面存的是指针,本质上是一个指针数组, 所以我们如果将字符串信息保留在栈帧中,那么当被释放的时候就找不到这个环境变量了,因此我们必须单独维护一段空间  环境变量是你在shell启动的时候从用户目录底下的配置文件读取的

    13410

    【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析

    加上 static , 相当于将全局变量的作用域缩小到了单个文件, 生命周期是整个程序的周期; 关于函数头文件的引申 :  -- 内部函数 : 单个文件中使用的内部函数, 仅在那个特定文件中定义函数即可...函数参数的传值调用和传址调用 (1) 传值调用 和 传址调用 传值调用 : 以传值的方式将参数传递给函数, 不能直接修改主函数中变量的值, 仅仅是将副本传递给了函数; 传址调用 : 将 变量的指针 传递给函数..., 因此函数执行完毕后, 主函数中的值是不变的; -- 传址调用 : swap_2 是传址调用, 传入的是 a , b 两个变量的地址 &a, &b, 当在swap_2 中进行修改的时候, 主函数中的...sizeof(int) * i 个字节; 将数组赋值给指针的途径 :  -- 将数组第一个元素地址赋值给指针变量 : p = &a[0]; -- 将数组地址赋值给指针变量 : p = a; 指针 和 数组...; a = p 和 a++ 会报错; 数组参数 :  -- 形参指针 : 将数组传作为参数传递给函数的时候, 传递的是数组的首地址, 传递地址, 形参是指针; 数组参数示例 :  -- 函数参数是数组

    3.9K20

    如何利用Ptrace拦截和模拟Linux系统调用

    但问题在于,一个进程一次只能够绑定一个tracer,因此我们无法在调试进程(GDB)的过程中模拟出一套外部操作系统,而另一个问题就是模拟系统调用将耗费更多的资源开销。...在这篇文章中,我将主要讨论x86-64架构下的Linux Ptrace,并且我还会使用到一些特定的Linux扩展。除此之外,我可能会忽略错误检查,但最终发布的完整源码将会解决这些问题。...(fork(2)),通过argv传递。...下一步就是收集系统调用信息,在不同的系统架构中这一步的实现方式也不同。在x86-64中,系统调用号是通过rax传递的,参数(最大为6)将传递给rdi、rsi、rdx、r10、r8和r9。...和wait(2),然后利用PTRACE_GETREGS获取结果,结果将存储在rax中: ptrace(PTRACE_GETREGS,pid, 0, ®s); fprintf(stderr," =

    1.9K70

    PHP脚本指南-解析GNU C风格命令行选项

    2020年新年第一文,冲鸭~来说一下PHP脚本开发时如何去解析对应的命令行选项 获取脚本名称 我们先来说一下如何获取当前执行的脚本是什么,我们可以使用$argv来获取,$argv包含当运行于命令行下时传递给当前脚本的参数的数组...,比如-v和--version,-h和--help等 $options短参数字符列表,该字符串中的每个字符会被当做选项字符,匹配传入脚本的选项以单个连字符-开头。...只允许 a-z、A-Z 和 0-9 $longopts长参数字符列表,此数组中的每个元素会被作为选项字符串,匹配了以两个连字符--传入到脚本的选项。...长参数由于是多字节,所以必须是数组,否则没法分隔 以上的两个参数字符后用单独的字符表示不接受传值;后面跟随一个冒号:的字符表示此选项需要值(必填);后面跟随两个冒号::的字符表示此选项的值可选 下面我们来看一下具体代码示例...,程序两个值都会收到,需要我们自己判断短参数和完整参数使用哪个。

    1.2K70

    从一道 CTF 题看 SROP | PWN

    返回时,rax中包含了系统调用的结果,而且只有INTEGER或者MEMORY类型的值才会被传递给内核。 用户接口 x86-64下通过寄存器传递参数,这样做比通过栈具有更高的效率。...它避免了内存中参数的存取和额外的指令。根据参数类型的不同,会使用寄存器或传参方式。如果参数的类型是MEMORY,则在栈上传递参数。...通过写入 n 个程序其实地址来让程序不会退出,多次从标准输入中读取 2....获取到栈地址后,可以使用 sigreturn 来获取shell了,但是目标程序中没有 gadget: syscall;retn ,我们需要使用将 rax 设置为 15 ,之后 syscall 的方式来进行...获取到栈地址后,可以使用 sigreturn 来获取shell了,但是目标程序中没有 gadget: syscall;retn ,我们需要使用将 rax 设置为 15 ,之后 syscall 的方式来进行

    1K20

    10.5 认识XEDParse汇编引擎

    XEDParse 是一款开源的x86指令编码库,该库用于将MASM语法的汇编指令级转换为对等的机器码,并以XED格式输出,目前该库支持x86、x64平台下的汇编编码,XEDParse的特点是高效、准确、...易于使用,它可以良好地处理各种类型的指令,从而更容易地确定一段程序的指令集。...XEDParse库可以集成到许多不同的应用程序和工具中,因此被广泛应用于反汇编、逆向工程、漏洞分析和入侵检测等领域。.../XEDParse.dll中的动态链接库放入到当前程序的根目录下,运行这个程序并输入一条汇编指令,则会输出该汇编指令所对应的机器码,输出效果图如下图所示; 读者也可以通过数组的方式传递一批汇编指令,并依次循环输出这些指令的机器码...,如下代码中定义了OpCode数组,该数组内可写入一些汇编指令集并以endp作为结束标志,通过循环调用XEDParseAssemble(&xed)的方式,实现批量输出机器码的效果; int main(int

    20120

    入侵检测之syscall监控

    5️⃣Linux入侵检测之syscall监控 6️⃣linux入侵检测之应急响应 0x01:Syscall简介 内核提供用户空间程序与内核空间进行交互的一套标准接口,这些接口让用户态程序能受限访问硬件设备...的调用 0x04:持久化之syscall监控 trap命令允许程序指定将在接收到中断信号后执行的命令。...开启另外的终端,监听本地的4444端口 反向跟踪,可以看到调用的syscall为ptrace 0x06:持久化之文件属性syscall监控 在权限提升和持久化中,设置setuid或setgid位,使应用程序将分别以拥有用户或组的特权运行...传递给攻击端的控制端。...反向跟踪隐藏痕迹中的修改的时间戳 其对应的参考syscall为settimeofday、clock_settime 、adjtimex等 0x10:syscall监控小结 下表中根据分类总结列举了部分常用的

    2.6K10

    10.5 认识XEDParse汇编引擎

    XEDParse 是一款开源的x86指令编码库,该库用于将MASM语法的汇编指令级转换为对等的机器码,并以XED格式输出,目前该库支持x86、x64平台下的汇编编码,XEDParse的特点是高效、准确、...易于使用,它可以良好地处理各种类型的指令,从而更容易地确定一段程序的指令集。...XEDParse库可以集成到许多不同的应用程序和工具中,因此被广泛应用于反汇编、逆向工程、漏洞分析和入侵检测等领域。.../XEDParse.dll中的动态链接库放入到当前程序的根目录下,运行这个程序并输入一条汇编指令,则会输出该汇编指令所对应的机器码,输出效果图如下图所示;图片读者也可以通过数组的方式传递一批汇编指令,并依次循环输出这些指令的机器码...,如下代码中定义了OpCode数组,该数组内可写入一些汇编指令集并以endp作为结束标志,通过循环调用XEDParseAssemble(&xed)的方式,实现批量输出机器码的效果;int main(int

    31320
    领券