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

网站建设玖金手指谷哥十中国互联网网站性能

网站建设玖金手指谷哥十,中国互联网网站性能,在哪里可以学做网站,网站开发角色分类文章目录 比较流行的汇编语言有3种:不同风格的汇编语言在语法格式上会有不同: 实战代码#xff1a;Intrinsic函数手写汇编#xff08;8086汇编#xff09;调用C的API库函数调用约定实际代码 C调用汇编函数进行计算纯C实现如下#xff1a;CASM实现:纯ASM实现:ASM打印命令行参… 文章目录 比较流行的汇编语言有3种:不同风格的汇编语言在语法格式上会有不同: 实战代码Intrinsic函数手写汇编8086汇编调用C的API库函数调用约定实际代码 C调用汇编函数进行计算纯C实现如下CASM实现:纯ASM实现:ASM打印命令行参数数据段存储 融合了一些自己之前的笔记 比较流行的汇编语言有3种: NASM风格的Intel汇编语言(x86\64)ATT风格的GAS汇编语言(特点是寄存器前面有%号)(Arm)Windows风格的汇编语言 不同风格的汇编语言在语法格式上会有不同: GAS(GNU Assembler)NASM(Netwide Assembler)MASM(Microsoft Macro Assembler) descriptGASNASMMASM寄存器push %eaxpush eax立即数push $1push 1给寄存器赋值1mov $1,%eaxmov eax,1 实战代码 ATT风格 000000000040056a add:40056a: 55 push %rbp40056b: 48 89 e5 mov %rsp,%rbp40056e: 89 7d ec mov %edi,-0x14(%rbp)400571: 89 75 e8 mov %esi,-0x18(%rbp)400574: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)40057b: 8b 55 ec mov -0x14(%rbp),%edx40057e: 8b 45 e8 mov -0x18(%rbp),%eax400581: 01 d0 add %edx,%eax400583: 89 45 fc mov %eax,-0x4(%rbp)400586: 8b 45 fc mov -0x4(%rbp),%eax400589: 5d pop %rbp40058a: c3 retq 40058b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)Intel风格 000000000040056a add:40056a: 55 push rbp40056b: 48 89 e5 mov rbp,rsp40056e: 89 7d ec mov DWORD PTR [rbp-0x14],edi400571: 89 75 e8 mov DWORD PTR [rbp-0x18],esi400574: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x040057b: 8b 55 ec mov edx,DWORD PTR [rbp-0x14]40057e: 8b 45 e8 mov eax,DWORD PTR [rbp-0x18]400581: 01 d0 add eax,edx400583: 89 45 fc mov DWORD PTR [rbp-0x4],eax400586: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]400589: 5d pop rbp40058a: c3 ret 40058b: 0f 1f 44 00 00 nop DWORD PTR [raxrax*10x0]使用汇编编写功能函数(使用GNU-Gcc编译因为clang会无法通过语法检查): //gcc main.c -masmintel #includestdio.h//intel 64 中参数一为rdi \参数二为rsi \返回值为rax //pop rbp为收栈准备返回main函数地址 int info(int x,int y){asm(add rdi,rsi;mov rax,rdi;pop rbp;ret;); }int main(){printf(%d\n,info(1,1));return 0; }Intrinsic函数 是编译器提供的函数接口调用Intrinsic函数可以达到代替汇编的作用 TODO 手写汇编8086汇编 demo.asm 环境必须是Linux Intel 64系统 ; nasm -felf64 demo.asm ld demo.o ./a.outglobal _start section .text_start:;write(1,message,13)mov rax,1mov rdi,1mov rsi,messagemov rdx,13syscall;exit(0)mov eax,60xor rdi,rdisyscallmessage:db Hi~,0xadb Hi~~,0xadb Hi~~~,0xamessage2:data1 db hellodata2 db world编译并运行 ~ $ nasm -felf64 demo.asm ld demo.o ./a.out Hi~ Hi~~ Hi~~~-f elf64 将源文件编译为64位的elf文件ld 将目标文件连接为可执行程序 代码解释 ; : 代码注释的符号表示这一行代码注释 global _start : 定义全局函数 section .text : 表示下面的代码段为.text段在C语言中你编写的代码段最终会通过编译器变为汇编代码放在.text段 _start: : 表示一个函数的开始声明函数域C语言中就是由_start函数开始初始化程序然后再调用熟悉的main函数 mov rax,1 : 当rax为1时 执行下面syscall等同于执行write()函数,其中原理就是系统调用比如你将rax为2时则会调用open()函数 mov rdi,1mov rsi,messagemov rdx,13这一块就是构造函数调用时的参数上面我声明了必须是64bit的系统因为rdi、rsi、rdx就是64bit ELF文件中的常用寄存器 64bit ELF文件中调用函数时会将参数从左到右放入寄存器寄存器分别为顺序: rdi, rsi, rdx, rcx, r8, r9。 可以注意到这里只有6个寄存器一旦超过6个参数时就会按照32bit ELF文件的规则将参数“从右至左”依次压入栈空间进行传递 ​ 那么这里就很容易理解了其实就是构造了3个参数(1,message,13)这里的message就是一个字符串常量的地址 syscall : 执行系统调用。即调用函数write(1,Hi~,13)exit(0) : 也是一样的方式调用,(xor就是异或操作即rdi rdi ^ rdi 0)message : 表示数据标签段db : 定义字节类型的数据,表示其后的数据都是字节型数据,后面的,0xa表示换行0xa就是\n的ASCLL码值 调用C的API库 ;nasm -felf64 demo.asm gcc demo.o -no-pie -static ./a.outglobal mainextern putssection .text main:mov rdi, messagecall putsret message:db hello, 0因为是使用gcc链接器那么就只需要写一个main函数入口如果还有个_start函数的话就会有冲突错误 注意这里的编译需要关闭PIE保护动态地址才能编译成功同时需要开启静态编译才能防止报段错误具体可以用gdb开查看实现 比如我关闭了PIE保护和开启了静态编译那么我的main函数地址地址每次都会是0x4016c0并且puts函数的地址也被程序正确的找到 ────────────────────────────────────────────────────── code:x86:64 ────0x4016b5 frame_dummy53 cs nop WORD PTR [raxrax*10x0]0x4016bf frame_dummy63 nop0x4016c0 main0 movabs rdi, 0x4016d0→ 0x4016ca main10 call 0x40c080 puts↳ 0x40c080 puts0 endbr640x40c084 puts4 push r130x40c086 puts6 push r120x40c088 puts8 mov r12, rdi0x40c08b puts11 push rbp0x40c08c puts12 push rbx ────────────────────────────────────────────── arguments (guessed) ──── puts ($rdi 0x000000004016d0 → 0x2e66006f6c6c6568 (hello?),$rsi 0x007fff184836e8 → 0x007fff184856d5 → /home/hi/a.out,$rdx 0x007fff184836f8 → 0x007fff184856e4 → SHELL/bin/bash,$rcx 0x00000040004000 )函数调用约定 在操作函数跳转时栈无疑是一个非常重要的通道而决定栈空间数据使用顺序声明的就是函数的调用约定声明了存在如下常用调用约定 TODO:还需要搞清楚其他的调用约定用法做好是有代码演示 stdcall (pascal) 主要用于Microsoft C系列cdecl 默认C语言调用约定fastcall thiscall naked call在默认C语言调用约定中64bit 传递参数时按照从左到右的顺序将尽可能多的参数依次保存在寄存器中。存放位置的寄存器顺序是确定的 对于整数和指针rdirsirdx rcxr8r9。对于浮点数float 和 double 类型xmm0xmm1xmm2 xmm3xmm4xmm5xmm6xmm7。 剩下的参数将按照从右到左的顺序压入栈中并在调用之后 由调用函数推出栈 在进入到另一个函数地址时会首先进行一个开栈操作至于开多少取决于你的函数代码块有多少和编译器 如果手写汇编的话就需要自己手动计算需要开辟的栈空间大小 为了更好看清楚栈空间的结构这里使用32bit程序来看效果 比如在main函数调用子函数时 处理完成调用参数后会执行call 0xxxxxx的指令 call会在调用函数时将eip压入栈也就是将下一条指令的地址赋值给esp这样就可以通过ret指令进行返回原函数继续执行了 然后到了子函数的地址处时 会执行先保存当前的栈底(ebp)值然后分别将ebp、esp压入栈通过sub esp,0xxxxx的方式来扩展栈空间 之后就是取main函数在调用子函数时的压入的参数了 子函数返回时 会通过执行leave指令其实就是 mov esp , ebp 来关闭开辟的栈空间然后pop ebp 移动到上个函数的位置 这时ebp就是函数入口时push上个函数的ebp的值最后根据这个值进行恢复 再执行ret指令进行地址跳转而ret指令就是 pop eip将堆栈段中当前SS:SP所指的字内容弹出到某个寄存器,也就是将sp的值赋值给eip,eip就是下一条指令地址 对应arm的pc寄存器这就对应了call指令时压入栈的ip地址 实际代码 执行leave指令前 00:0000│ esp 0xffffd508 —▸ 0x56558fdc (_GLOBAL_OFFSET_TABLE_) ◂— 0x3ee4 01:0004│ 0xffffd50c —▸ 0x56556273 (__libc_csu_init83) ◂— add esi, 1 02:0008│ 0xffffd510 ◂— 0x1 03:000c│ 0xffffd514 ◂— 0x1 04:0010│ ebp 0xffffd518 —▸ 0xffffd538 ◂— 0x0 05:0014│ 0xffffd51c —▸ 0x56556208 (main45) ◂— add esp, 8 06:0018│ 0xffffd520 ◂— 0x4 07:001c│ 0xffffd524 ◂— 0x2执行leave指令后 00:0000│ esp 0xffffd51c —▸ 0x56556208 (main45) ◂— add esp, 8 01:0004│ 0xffffd520 ◂— 0x4 02:0008│ 0xffffd524 ◂— 0x2 03:000c│ 0xffffd528 ◂— 0x0 04:0010│ 0xffffd52c ◂— 0x0 05:0014│ 0xffffd530 ◂— 0x1 06:0018│ 0xffffd534 ◂— 0x2 07:001c│ ebp 0xffffd538 ◂— 0x0intel架构默认调用约定组成结构 32位无参数 payload ba* 0x88 bb * 0x4 p32(backdoor) p32(main_addr)32位有参数函数地址返回地址参数 payload ba* 0x88 bb * 0x4 p32(backdoor) p32(main_addr) p32(bin_sh)//完整的rop链返回地址main64无参数 payload ba* 0x88 bb * 0x8 p64(backdoor) 64有参数函数地址参数返回地址” paypyload ba* 0x88 bb * 0x8 p64(pop_edi) p64(bin_sh) p64(backdoor)64无System泄露: #第一次加载payload进行libc真实地址获取 payload ba * 0x50 bb * 0x8 p64(prdi) p64(e.got[puts]) p64(e.plt[puts]) p64(返回函数地址) #重新构造payload payload ba * 0x50 bb * 8 for i in range(1):payload p64(rtn_addr) payload p64(prdi) p64(libc_addr lic.dump(str_bin_sh)) p64(libc_addr libc.dump(system))C调用汇编函数进行计算 特点环境下说使用simd的一些优化操作就需要使用simd指令集来操作数据从而实现快速计算那么此时的汇编代码块就起到了一个处理数据集功能的作用 纯C实现如下 #includestdio.h #includetime.hint Max(int a,int b,int c){int ret a;if(retb) retb;if(retc) retc;return ret; }int main(){srand(0x100); //为了方便ASM 和 C代码分别实现的demo运行结果对比这里使用一样的随机种子for (int i 0; i 10; i) {int a rand() , b rand(), c rand();printf({%d,%d,%d} Max%d \n,a,b,c,Max(a,b,c));}return 0; }结果 ~ $ gcc main.c ./a.out {1557381903,485784087,974190345} Max1557381903 {909832560,185226890,4869305} Max909832560 {842916993,1066023196,370971114} Max1066023196 {1378714000,834802215,875669745} Max1378714000 {419994512,459245563,1733189616} Max1733189616 {259238441,2032537841,1291879760} Max2032537841 {1977168301,1893959658,2072065736} Max2072065736 {1802926432,786500781,937118081} Max1802926432 {1567600346,303276252,249486295} Max1567600346 {2134477068,1322435152,1593906562} Max2134477068CASM实现: demo.asm global Maxsection .textMax:mov rax,rdicmp rax,rsicmovl rax,rsicmp rax,rdxcmovl rax,rdxretmain.c #includestdio.h #includetime.hint Max(int a,int b,int c);int main(){srand(0x100);for (int i 0; i 10; i) {int a rand() , b rand(), c rand();printf({%d,%d,%d} Max%d \n,a,b,c,Max(a,b,c));}return 0; }结果 ~ $ nasm -f elf64 demo.asm gcc main.c demo.o ./a.out {1557381903,485784087,974190345} Max1557381903 {909832560,185226890,4869305} Max909832560 {842916993,1066023196,370971114} Max1066023196 {1378714000,834802215,875669745} Max1378714000 {419994512,459245563,1733189616} Max1733189616 {259238441,2032537841,1291879760} Max2032537841 {1977168301,1893959658,2072065736} Max2072065736 {1802926432,786500781,937118081} Max1802926432 {1567600346,303276252,249486295} Max1567600346 {2134477068,1322435152,1593906562} Max2134477068纯ASM实现: ASM打印命令行参数 global mainextern putssection .textmain:push rdi ;保存参数一push rsi ;保存参数二;sub rsp,8 ;实际在操作的时候在进入main函数时因为使用的程序是64bit可能需要手动的修复rbp的值不然会导致栈空间数据错乱mov rdi ,[rsi]call puts;add rsp,8 ;回收栈pop rsi ;取出原参数值pop rdi ;取出原参数值add rsi,8dec rdijnz mainret运行 ~ $ nasm -f elf64 demo.asm gcc demo.o -static ./a.out 1 2 3 ./a.out 1 2 3调试 首先来看看进入main函数时的寄存器值 $rax : 0x000000004016c0 → main0 push rdi $rbx : 0x007ffeccff0100 → 0x007ffeccff06e4 → SHELL/bin/bash $rcx : 0x154000 $rdx : 0x007ffeccff0100 → 0x007ffeccff06e4 → SHELL/bin/bash $rsp : 0x007ffeccfefef8 → 0x00000000401b0a → __libc_start_call_main106 mov edi, eax $rbp : 0x1 $rsi : 0x007ffeccff00d8 → 0x007ffeccff06cf → /home/hi/a.out $rdi : 0x4 $rip : 0x000000004016c0 → main0 push rdi可以看到rdi为4表示main的第一个参数的值为4即命令行参数有4个 然后看看此时的rsi: gef➤ telescope $rsi 0x007ffeccff00d8│0x0000: 0x007ffeccff06cf → /home/hi/a.out ← $rsi, $r13 0x007ffeccff00e0│0x0008: 0x007ffeccff06de → 0x4853003300320031 (1?) 0x007ffeccff00e8│0x0010: 0x007ffeccff06e0 → 0x4c45485300330032 (2?) 0x007ffeccff00f0│0x0018: 0x007ffeccff06e2 → 0x3d4c4c4548530033 (3?) 0x007ffeccff00f8│0x0020: 0x0000000000000000刚好对应着我们传进来的参数。并且最后一个参数后面的地址被置为0 可以看到在main函数开始时进行了2个push操作这是为了保存main函数的2个参数地址因为在调用call puts的时候必须要保证rdi为参数二的字符串值在进入puts函数的子函数栈空间后同时也会操作rdi的值这个时候如果没有在调用puts函数之前保存地址的话那么就会发生指针丢失的问题从而产生各种可能的错误调用puts函数后进行了一个恢复参数值的操作从而方便再次进入到main函数进行一个相同的操作dec指令表示自减1执行结果影响AF、OF、PF、SF、ZF标志位 jne指令 ZF寄存器!0则跳转,这里主要关注ZF标志位来看调试 ────────────────────────────────────────────────────── code:x86:64 ────0x4016ca main10 pop rsi0x4016cb main11 pop rdi0x4016cc main12 add rsi, 0x8 ●→ 0x4016d0 main16 dec rdi0x4016d3 main19 jne 0x4016c0 main0x4016d5 main21 ret0x4016d6 main22 cs nop WORD PTR [raxrax*10x0]0x4016e0 handle_zhaoxin0 push rbx0x4016e1 handle_zhaoxin1 mov eax, 0x4在执行最后一个参数时执行dec指令前的flags寄存器如下 gef➤ p $eflags $8 [ AF IF ] //AF IF表示只有这两个寄存器的值为1 gef➤ x $eflags 0x212gef➤ p $eflags $7 [ PF ZF IF ] //ZF 可以看到这里的ZF寄存器值为1了即表示dec指令执行后的值为0,那么就会在jne指令后满足不为zero寄存器不为0的条件进行 gef➤ x $eflags 0x246具体的flag寄存器标记为如下: value溢出方向中断跟踪符号零辅进位奇偶进位markOFDFIFTFSFZFAFPFCF0x2120010000100100x246001001000110 数据段存储 ;nasm -f elf64 demo.asm gcc demo.o -static ./a.out 1 2global main;C APIextern atoiextern printfdefault relsection .text main:dec rdijz nothingToAveragemov [count], rdi; 保存浮点数参数的个数到bss变量 accumulate:push rdipush rsimov rdi, [rsirdi*8]; argv[rdi]call atoipop rsipop rdiadd [sum], raxdec rdijnz accumulate; loop遍历参数average:cvtsi2sd xmm0, [sum]cvtsi2sd xmm1, [count]divsd xmm0, xmm1; xmm0 现在值为 sum/countmov rdi, format; printf输出格式mov rax, 1; printf 是多参数的, 含有一个不是整数的参数sub rsp, 8; 对齐栈指针call printfadd rsp, 8retnothingToAverage:mov rdi, errorxor rax, raxcall printfret;.data段section .data count: dq 0 sum: dq 0 format: db %g, 10, 0 error: db There are no command line arguments to average, 10,0~ $ nasm -f elf64 demo.asm gcc demo.o -static ./a.out 1 2 1.5
http://www.hkea.cn/news/14350480/

相关文章:

  • 济南网站制作技术交流wordpress包
  • 大良网站建设如何赚钱项目
  • 博物馆网站建设方案有个人免费网站吗
  • 摄影网站建设目的永久云服务器免费领
  • 重庆公司网站搭建公司推荐浙江公司响应式网站建设推荐
  • 百度官网网站wordpress 域名分离
  • 网站编辑做多久可以升职仿皮皮淘网站开发全程培训
  • 域名解析查询站长工具本科毕业 做网站编辑
  • 做网站第一步要干啥vi设计作品图
  • 域网站名分类国外常用的seo站长工具
  • 企业手机网站建设流程图企业展厅设计公司哪家好怎么样
  • 淘宝网做宝贝详情用哪个网站怎样做建网站做淘客
  • 建网站费用明细c s网站开发模式
  • 塘厦建设网站做盗版电影网站教程
  • 哪些园林网站可以做外链小型企业网络配置实例
  • 广州注册公司代理网站优化 价格
  • 汉力建设网站wordpress 优化seo插件
  • 湖南网站建设哪里好广西建设工程质量检测协会网站
  • 手机在线销售网站 - 百度本地wordpress 慢
  • 房产中介网站开发费用苏州建设交通职业技术学院
  • 云梦县城乡建设局网站凡科快图在线制作免费官网下载
  • 巴中微小网站建设案例彩票网站html模板
  • 百度做网站和推广效果怎么样vue.js做网站
  • 网站建设实训报告目的网站突然被降权
  • 哈尔滨建筑专业网站移动网站建设推广
  • 概述网站建设的流程永久无限免费看的app
  • 列出寻找网站关键词的几种途径wordpress 增加数据表
  • 站长工具无吗经典高端旅游定制网站
  • 东莞企业网站seo手机端网站开发教程
  • 找人做网站需要注意什么权大师的网站是哪个公司做的