[0x0a]段的数量。[0x0c]段重定位表的开始汇编地址。 加载过程 读取用户程序所在磁盘的扇区,然后加载进内存某个地址,用户程序头部的信息,根据加载的地址修改段重定位表。...,然后,根据用户程序头部信息的程序大小除以512获取程序占据的扇区数(这里程序占据扇区是连续的),然后判断是否继续读取,要注意的是我们已经读取了一个扇区。...如果用户程序加载到0x10000处,段地址为0x1000,每次读取一个字节逻辑地址就要+1, 0x0000 开始,一直延伸到最大值 0xffff。...要解决这个问题最好的办法是,每次往内存中加载一个扇区前,都重新在前面的数据尾部构造一个新的逻辑段,并把要读取的数据加载到这个新段内。...; 答案是不会的,因为内存从0x00000到0xFFFFF,最大1MB, ; 所以这里的地址除以16也就是右移四位,刚好商就算最大也才FFFF。所以这样。
,不然整体也就不会才几千行代码。...,有详细的注释我就不解释了,如果有哪儿不懂,可回去熟悉熟悉 ELF文件格式 所以 $bootmain$ 就做了一件事,将内核加载到内存,加载内核又分了两步: 读取内核 $elf$ 文件头到 $0x10000...$ 函数的意思是从磁盘的 1 扇区读取 4096字节到物理地址 $0x10000$ 处。...内核文件在磁盘的扇区 1 ,注意这里虽然参数传的是 0,但是函数内部加了 1,所以是从扇区 1 读取的。这个函数后面讲述磁盘再详述,这里知道作用就行。 $0x10000$ 有什么意义?...此时的内存布局: $end$ 为内核末尾地址,不同版本有稍许不同,可以在 $kernel.sym$ 文件中查找,也可以直接读取 $elf$ 的程序头,根据 $PhysAddr + MemSize$ 计算出来
这样全世界的机器都使用这个字符集,那么就不会出现乱码了 那么 Unicode 肯定是一个非常大的字符集合了,现在大概收集了一百多万个字符 那么就有一个问题 Unicode 怎么给字符分配唯一 ID?...这样根据字符自动分配合适字节,的确挺好的,但是机器在读取二进制的时候,怎么知道读取多少位是一个字符??...比如 上面例子说的,编码 1D785 大于 0x10000, 所以 拆成两个 0xD835 0xDF85 第一区间是 D800 到 DBFF,第二个区间是 DC00 到 DFFF 我们以 D800 为例...把一个 大于 0x10000 的字符 ,换算成 两个在某区间内的 值 分成两部分再拼上 110110, 110111 为什么我不能直接拼上 110110, 110111??...你知道的, 0x10000 和 0x10FFFF 的字符,16进制编号必定在第五位是大于等于1 的,如下图 ?
那么有一个问题,ASCLL 标准的字符采用的一个字节进行编码方式,而我们的中文汉字采用的两个字节进行编码,计算机在解码的时候究竟是一次读取一个字节并把它按照 ASCLL 标准解析成一个字符,还是一次读取两个字节并把它按照我们的...这样,由于 ASCLL 标准的所有字符(00000000-01111111),最高位都是 0,所以当计算机读取到某个字节的最高位为 1 的时候,就连着读取两个字节按照 GB2312 标准解析为一个汉字,...** UTF-16 的解决办法如下: 每个 Unicode 字符都有一个自己的 Unicode 编号,并且对于增补字符来说,他们的编号都大于 0x10000 。...这个序号的值必然位于范围:0x00000 - 0xFFFFF 之间,占 20 个比特位 ,因为剩下的增补字符数目不会超过 0xFFFF 个。...2、Unicode 编号 U+24B62 的字符 首先,判断该字符的编号值是大于 0x10000 的,说明该字符隶属于增补字符集。
上次已经学到了 CPU为访问内存做好了准备,把一些重要寄存器的值都设置好了。 今天我们主要一起学习,操作系统是如何把自己从硬盘给弄到内存里的?...现在的状态已经把ds,es,cs设置好了,从CPU的角度看,已经知道如何访问内存了。...发起13号中断后,就会去中断向量表找到13号中断程序的地址,然后跳转过去执行,感觉有点像执行一个函数。 13号中断程序是BIOS写好的,就是读取硬盘的函数。...随着我们阅读越来越多的代码,也会接触到更多的中断程序,各模块会注册自己的中断处理程序。...就是从 把硬盘的第6个扇区到240个扇区,加载到内存0x10000处。 和上面从硬盘复制是一样的。
system loaded at 0x10000 (65536). // system模块的末地址,即首地址+大小 ENDSEG = SYSSEG + SYSSIZE !.../ jb ok1_read ret // 算出需要读取的扇区数,并且判断读取完后会不会超过当前es:bx所能表示的范围,不会则开始读,否则只读所能表示的范围内的扇区数 ok1_read:...读取后会大于当前es:bx所能表示的范围 xor ax,ax sub ax,bx // 判断在当前es:bx可表示的范围内,还能读取多少个扇区 shr ax,#9 /*...mov sread,ax // cx是刚才读取成功的扇区数 shl cx,#9 // 更新bx的值,es:bx指向的内存存放着从软盘读取的数据 add bx,cx...// CF=0则跳转,说明还没有超过es:bx所能指向的内存范围,继续读,往es:bx继续写数据 jnc rp_read /* 否则CF=1则往下走,说明刚才读取的数据超过了当前
addi r2,r1,1 r2=r1+1 寄存器寻址 操作数为寄存器中的值 add r2,r1,r0 r2=r1+r0 基址寻址 以基址寄存器中的值和立即数常数之和作为地址,该地址指向的内存的值作为操作数...r1则程序跳到label处 伪直接寻址 跳转地址由指令中26位地址左移两位(即乘以4)与PC计数器的高4位相连所组成 j label WinMIPS64汇编指令 助记 从内存中加载数据 lb lb... CONTROL: .word 0x10000 DATA: .word 0x10008 WinMIPS64 模拟器支持内存映射 IO 模型,用于写入 或 从 WinMIPS64 终端读取...要写入终端: 将内存地址设置为要写入的值DATA 将适当的值写入内存地址CONTROL 要从终端读取: 将适当的值写入内存地址CONTROL 从内存地址读取输入DATA CONTROL...用法 写入操作 1 设置为输出的无符号整数DATA 2 设置为输出的有符号整数DATA 3 设置为输出的浮点值DATA 4 设置为用于输出的字符串的内存地址DATA 5 设置为像素的坐标、坐标和 RGB
CSP获取RSA_AES提供者句柄,导入RSA 私钥句柄,这是用于解密dll KEY BLOB(篇幅过长,仅显示部分) 读取被加密dll文件信息,加密文件头部含有经2048RSA加密过的AES密钥得到的...256字节密文 解密256字节密文得到16字节明文(AES密钥)再用AES密钥解密文件得到dll 注:这时可以从内存中dump出dll文件(我的方式是直接从OD内存中复制16进制,粘贴到010ed...实现:修复IAT,修复重定位,修复区段内存属性,调用tls, 调用DllEntryPoint 获取并调用dll唯一的一个导出函数 2.加密(StartSchedule) Ⅰ.总览 Ⅱ.细分...,进行判断是否经过处理,并检查其类型 2.对于小文件,创建新文件,其名为原文件后加T 3.对于大文件,将前0x10000字节复制到文件尾部,并清空前0x10000字节 4.生成随机AES密钥,用RSA...encrypt_and_wirte_junk_data 二、解密程序 解密程序为vc6.0 MFC 程序,根据命令行参数,有三种不同功能 OnInitDialog内部: 1.命令行参数为
举个例子, 字符串 uint8* hell = "hell world"编译后,运行前保存在ROM中的地址 A, 在运行时被加载到内存中 B, 这里 A 就是加载时地址, 而程序运行时读取的地址时B,...汇编程序中 ENTRY 伪操作定义的, 通常用于标志异常处理程序入口,这样连接器删除无用段时,不会把该段代码删除。...,完成程序加载工作), 如下一个文件的组织情况 : ?...from arm 例子 一个加载时域 映像文件保存在 0x10000 地址, 运行的时候, 从该地值读取数据加载到指定区域(运行时域没有指定, 同加载时域,并按配置文件分类存放) LR_1 0x010000...AT 用来指明需要 run-time 拷贝的数据。 SECTIONS { . = 0X10000; /* .
JSON 中的普通转义字符 个人认为,JSON 是目前针对程序员而言可读性(readability)最佳的数据传输格式之一,并且 JSON 完整地考虑到了数据传输中的转义,避免出现各种注入风险。...JSON 中针对 Unicode 字符的处理 这里所说的 Unicode 字符,准确而言指的是在 ASCII 范围之外的字符,也就是值大于 0x7F 的 Unicode 字符。...在 ASCII 为主的数据传输中,这种编码方式比较稳妥,并且不会额外增加过多的数据量。当然对于 Unicode 字符比较多的情况下(比如大量的中文),这就需要程序员考虑一下额外带来的网络花销了。...大于 65535 的字符要怎么表示呢?首先,绝对不是简单地采用 \uXXXXX,这会导致编码错误。 针对大于 65535 的字符,JSON 采用的是 UTF-16 编码。...比如我们用 u 代表这样的一个字符,UTF-16 的处理方法如下: 首先,u = u - 0x10000 取 hi 等于做了减法之后的 u 的高10位:hi = (u & 0xFFC00) >> 10
注意在某些情况下,使用FIXED和 单个加载区域是不合适的。指定固定位置的其他方式是: 如果您的加载程序可以处理多个加载区域,请将 RO 代码或数据放在其自己的加载区域中。...要将数据结构放置在内存映射 I/O 的位置??,请使用两个加载区域并指定UNINIT. UNINIT确保内存位置不会被初始化为零。...和ARM_LIB_HEAP都需要,因为程序将与半主机库链接。...内存块不构成加载区的一部分,而是在执行时分配使用。...ZI区域在运行时不会初始化为零。
,程序员将GDT设定在内存中某个位置之后,可以通过 LGDT 指令将 GDT 的入口地址装入此积存器,从此以后,CPU 就根据此积存器中的内容作为 GDT 的入口来访问GDT了。...读取8个扇区大小的ELF头到内存地址0x10000 校验ELF header中的模数,判断是否为0x464C457FU 读取ELF header中的程序段到内存中 跳转到操作系统入口 定义ELF头指针...,指向0x10000 读取8个扇区大小的ELF头到内存地址0x10000 校验ELF header中的模数,判断是否为0x464C457FU 读取ELF header中的程序段到内存中 跳转到操作系统入口...定义ELF头指针,指向0x10000 读取8个扇区大小的ELF头到内存地址0x10000 校验ELF header中的模数,判断是否为0x464C457FU 读取ELF header中的程序段到内存中...跳转到操作系统入口 bootloader如何读取硬盘扇区的 bootloader是如何加载ELF格式的OS bootloader如何读取硬盘扇区的 * bootloader进入保护模式并载入c程序
\n"); } printf("程序或DLL最低可用内存地址: 0x%X\n", si.lpMinimumApplicationAddress); printf("程序或DLL最高可用内存地址:...1111\n", si.dwActiveProcessorMask); /// 常用于获得当前可处理数据的子线程 printf("当前组中的逻辑处理器个数: %d 个\n", si.dwNumberOfProcessors...); printf("页面分配粒度: 0x%x 字节\n", si.dwPageSize); printf("虚拟内存分配粒度: 0x%x 字节\n", si.dwAllocationGranularity...(); return 0; } 本机输出: 处理器架构: X64(AMD or Intel) 程序或DLL最低可用内存地址: 0x10000 程序或DLL最高可用内存地址: 0xFFFEFFFF 配置到系统的处理器...: 4095 15 = 0000 0000 0000 0000 0000 0000 0000 1111 当前组中的逻辑处理器个数: 12 个 页面分配粒度: 0x1000 字节 虚拟内存分配粒度: 0x10000
在进程的_EPROCESS中有一个_RTL_AVL_TREE类型的VadRoot成员,它是一个存放进程内存块的二叉树结构,如果我们找到了这个二叉树中我们想要隐藏的内存,直接将这个内存在二叉树中抹去,其实是让上一个节点的... #include int main(int argc, char *argv[]) { LPVOID p1 = VirtualAlloc(NULL, 0x10000...= " << p1 << std::endl; std::cout << "address2 = " << p2 << std::endl; getchar(); return 0; } 运行程序得到两个内存地址...process ffffe28fbb451080得到VAD地址ffffe28fbe0b7e40 此处以0xf00000为例,这里我们看到windbg中的值和进程中分配的内存地址并不完全一样,这是因为x86...cpu默认内存页大小4k也就是0x1000,所以这里还要再乘以0x1000才是真正的内存地址。
关于Squalr Squalr是一款功能强大的高性能内存编辑工具,同时它也是一款采用C#编写的黑客工具。...它允许用户在windows桌面游戏中创建和分享作弊方案,其中的功能包括内存扫描、指针、x86/x64程序集注入等等。 Squalr通过多线程结合SIMD指令的方式实现快速扫描。...NuGet包提供的API接口 接收引擎输出 如果使用的是NuGet包,最重要的是通过钩子挂接引擎的输出,并接收事件日志,这些数据对于诊断问题是非常重要的。...startAddress, endAddress); IEnumerable modules = Query.GetModules(); 汇编/反汇编 Squalr可以对x86/x64程序集进行汇编和反汇编...); Console.WriteLine(instructions[0].Mnemonic); 扫描功能 Squalr提供了一个API来执行高性能的内存扫描: using Squalr.Engine.Scanning
在进程的_EPROCESS中有一个_RTL_AVL_TREE类型的VadRoot成员,它是一个存放进程内存块的二叉树结构,如果我们找到了这个二叉树中我们想要隐藏的内存,直接将这个内存在二叉树中抹去,其实是让上一个节点的..., MEM_COMMIT, PAGE_READWRITE);LPVOID p2 = VirtualAlloc(NULL, 0x10000, MEM_COMMIT, PAGE_EXECUTE_READWRITE..."address = " 程序得到两个内存地址...process ffffe28fbb451080得到VAD地址ffffe28fbe0b7e40图片此处以0xf00000为例,这里我们看到windbg中的值和进程中分配的内存地址并不完全一样,这是因为x86...cpu默认内存页大小4k也就是0x1000,所以这里还要再乘以0x1000才是真正的内存地址。
CPU执行的第一条指令的地址 image.png BIOS程序在内存中加载中断向量表和中断服务程序 ?...调用INT 0x19中断,将软盘第一扇区(0面0磁道1扇区)的512字节即bootsect.s加载到内存0x07C00处 ?...调用INT 0x13中断,将setup.s对应的程序加载到0x90200处,共四个扇区2K 再通过INT 0x13中断,将system加载到0x10000 检查根设备 然后跳到setup.s的第一行指令...可见,bootsect主要完成的是搬运加载工作 setup setup程序的第一件事是利用BIOS中断服务程序将机器系统数据加载在原bootsect的位置(覆盖),0x90000~0x901FD,在setup...前只空了2个字节 关中断,将system从0x10000复制到0x00000 ?
,大于0x0800,小于0xFFFF,转换为UTF-8时占用3字节,需使用第三个模板,按顺序填入: 1110 0100 1011 1000 1000 0000 对应转换成十六进制表示 E4 B8...UTF-16: 存在一个起始字节序标记 FF FE 或 FE FF ,分别代表小端序和大端序,对于“一”的UTF-16(LE)的编码则是004E,数字1的编码为3100,这个内存顺序是小端序...四字节:大于等于U+10000的需要计算,方式如下: 假设字符的Unicode代码为U,最大是0x10FFFF。...令U' = U - 0x10000,那么U'的取值范围就是 0 ~ 0xFFFFF,20bits。...Unicode代码 U+1D4D1 ,UTF-16(BE) D8 35 DC D1 U' = 0x1D4D1 - 0x10000 = D4D1 = 0000 1101 0100 1101
hook,无论是使用E8 call,还是E9 jmp,都需要至少5个硬编码才能实现,所以这里我们找5个硬编码进行填入我们代码的操作,这里注意不能够找全局变量和重定位的地址,否则在进行还原的过程中可能地址已经发生改变导致程序不能够正常运行...jmp_code[0] = 0xE9; *(ULONG*)&jmp_code[1] = jmpAddr; 这里就需要写入内存了,这里需要关闭页的只读保护,定义一个ShutPageProtect函数将...CR0寄存器的WP位置0 //关闭页只读保护 __asm { push eax; mov eax, cr0; and eax, ~0x10000;...// 与0x10000想与后取反 mov cr0, eax; pop eax; ret; } 关闭页保护之后首先将之前的硬编码保存,再进行覆盖...; } } 那么到这里我们的hook代码就已经完成,因为我们已经将原来的硬编码存入了Old_code这个数组,这里我们编写UnHookNtOpenFile时利用RtlCopyMemory写会到原内存即可
首先CR3是什么,CR3是一个寄存器,该寄存器内保存有页目录表物理地址(PDBR地址),其实CR3内部存放的就是页目录表的内存基地址,运用CR3切换可实现对特定进程内存地址的强制读写操作,此类读写属于有痕读写...在读写进程之前需要先找到进程的PEPROCESS结构,查找结构的方法也很简单,依次遍历进程并对比进程名称即可得到。...Peprocess = NULL;DWORD PID = 6672;NTSTATUS nt = PsLookupProcessByProcessId((HANDLE)PID, &Peprocess);通过CR3读取内存实现代码如下...,我们读取Tutorial-i386.exe里面的0x0009EDC8这段内存,读出长度是4字节,代码如下。...DbgPrint("readbuf = %d \n", buffer);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}读出后输出效果如下:图片写出内存与读取基本一致
领取专属 10元无门槛券
手把手带您无忧上云