符号表

C++编译器和连接器原理

匿名 (未验证) 提交于 2019-12-02 23:57:01
本文转载自新浪永远即等待的博客 几个概念: 1、编译 :编译器对源文件进行编译,就是把源文件中的文本形式存在的源代码翻译成机器语言形式的目标文件的过程,在这个过程中,编译器会进行一系列的语法检查。如果编译通过, 就会把对应的CPP转换成OBJ文件 。 2、编译单元 :根据C++标准,每一个CPP文件就是一个编译单元。 每个编译单元之间是相互独立并且互相不可知 。 3、目标文件 :由编译所生成的文件,以机器码的形式包含了编译单元里所有的代码和数据,还有一些期他信息,如未解决符号表,导出符号表和地址重定向表等。目标文件是以二进制的形式存在的。 根据C++标准, 一个编译单元(Translation Unit)是指一个.cpp文件以及这所include的所有.h文件 ,.h文件里面的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件,后者拥有PE(Portable Executable,即Windows可执行文件)文件格式,并且本身包含的就是二进制代码,但是不一定能执行,因为并不能保证其中一定有main函数。 当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由链接器进行链接成为一个.exe或.dll文件 。 下面让我们来分析一下编译器的工作过程: 我们跳过语法分析,直接来到目标文件的生成,假设我们有一个A.cpp文件,如下定义: int

NOE77101固件后门漏洞分析

匿名 (未验证) 提交于 2019-12-02 23:51:01
最近学习vxworks固件的分析,尝试对noe77101固件的经典后门漏洞进行分析,就好比学习msf时练习经典的ms08-067一样。noe77101固件的 下载地址 在此。 拿到固件之后, unzip noe77101_OS.bin_.zip 解压固件,得到FLASH0文件夹和一个commandList.lst文件,FLASH0的文件目录如下: 在 flash0/wwwroot/conf/exec/ 目录下找到了NOE77101.bin文件,这应该就是我们要分析的目标了。 使用binwalk对.bin文件进行分析, binwalk NOE77101.bin ,结果如图所示 使用binwalk提取NOE77101.bin中的文件, binwalk -e NOE77101.bin ,得到217和217.zlib两个文件。使用binwalk分析217, binwalk 217 ,分析结果如图,可以看到此固件使用vxworks内核,binwalk还在固件中识别出了符号表。 现在需要确定固件的cpu架构、大小端格式和固件加载地址,才能使用ida pro进行反汇编。 使用binwalk的 -A 参数分析217文件, binwalk -A 217 ,结果如图所示,可知固件使用PowerPC架构,大端格式。 接下来还要确定固件的加载地址,vxworks固件的常见加载地址是0x10000

语法制导翻译――语义分析

匿名 (未验证) 提交于 2019-12-02 23:42:01
语义分析 和 中间代码生成 可以同时进行,称为 语义翻译 语法分析 、 语义分析 、 中间代码生成 可以同时进行,称为 语法制导翻译 参考: https://liuyehcf.github.io/2017/11/06/%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86-%E8%AF%AD%E6%B3%95%E5%88%B6%E5%AF%BC%E7%BF%BB%E8%AF%911/ /*--> */ /*--> */ /*--> */ /*--> */ /*--> */ SDT中的语义分析,和中间代码生成绑到一块了; 在花括号中执行语义动作(可以包括生成中间代码和类型检查),就认为是计算了节点属性; 而属性是什么完全是看需求来的。 步骤: /*--> */ /*--> */ /*--> */ /*--> */ /*--> */ 参考PLY在词法分析部分生成符号表,符号表参考要检查的错误类型确定其数据类型,P56标明使用SDT和使用符号表的关系 在语法分析构建语法分析树时添加语义动作,包括类型检查和中间代码生成。添加的动作在parser.py中尽量简洁,可以引入自定义模块,使用该模块中的方法。

指针和引用

﹥>﹥吖頭↗ 提交于 2019-12-02 11:16:08
1.为什么使用指针 1.1每一个编程语言都使用指针 C++将指针暴露给了 用户(程序员),而java和C#等语言则将指针隐蔽起来了。 1.2使用指针的有点和必要性: 指针能够有效的表示数据结构 能动态分配内存,实现内存的自由管理 能方便的使用字符串 指针直接与数据的存储地址有关。比如:值传递不如地址传递高效,因为值传递先从实参的地址中取值,再赋值给形参代入函数计算。而指针则把形参的地址直接指向实参地址,使用时直接取出数据,效率提高。(这里形参的改变会影响实参的值) 2.指针和引用的区别 2.1本质: 引用是别名,指针是地址 2.2具体: 2.2.1 从现象上看: 指针在运行时可以改变所指向的值,而引用一旦与某个对象绑定后就不再改变。意思是:指针可以被重新赋值以指向另一个对象,但是引用则总是在初始化时被指定的对象,以后不能改变,但是指向的内容可以改变。(下面是这个规则的理解) string str1 = "a"; string str3 = "b"; string &str2 = str1; str2 = str3; 我们看到了“str2 = str3”之后,str2指向的还是str1的地址,str2映射的地址没有发生改变,只是指向的内容发生了改变。 如果用&str2作为左值,编译器会报错,提示“表达式必须是可以修改的值”,这也就是而引用一旦与某个对象绑定后就不再改变的意思

编译链接是如何得到可执行文件的呢?

让人想犯罪 __ 提交于 2019-12-01 04:29:46
盘古开天辟地!我们写了个C语言源文件,那从源文件到可执行程序这中间又发生了什么?编译,链接这些概念又是什么意思?带着对这些问题的好奇,我查了一些资料。其中,主要参考的是《程序员的自我修养》这本书和一些网上的博客。 在 windows 下经常只需要单击 Run 或者 Debug 就可以运行一个C语言程序,这种便利隐藏了背后的复杂机制,而我想知道这背后到底发生了什么。 本文所使用的系统是 ubuntu ,但这些概念也适用于 windows 下。 1. 编译源文件的四个阶段 假如我们写了一个很简单的 helloworld.c 程序: #include <stdio.h> int main(int argc, char *argv[]) { printf("Hello,World!\n"); return 0; } 我们都知道运行命令 gcc helloworld.c -o helloworld 便可以对这个文件进行编译,并命名可执行文件为 helloworld 。然后运行 ./helloworld Hello,World! 便可以执行该文件,但是这背后又经历了什么呢? 注意: 本文并不是一篇严谨的探讨编译过程的文章,只是我对这个问题了解过程的一个梳理。 1.1 预处理(preprocessing) 在预处理阶段,我们可以简单理解就是处理以"#"开始的那些预处理指令,比如说:

STM32 & RT-Thread的逆向入门

ぐ巨炮叔叔 提交于 2019-12-01 01:35:27
STM32 & RT-Thread的逆向入门 backahasten@0xFA ​ 现在,各种MCU的价格越来越低,同等条件下能买到的ROM和RAM资源也多了。对一些复杂逻辑的应用,相比于花费大量的时间去扣底层还不如使用操作系统加快开发速度,使用了操作系统之后,针对固件的逆向会比无os的固件逆向有一些不同。 ​ RT-Thread是国产实时操作系统的典范,我个人的特别喜欢。RT-Thread有很多的BSP可以适配众多的芯片和架构,在本文还是使用最常见的stm32来进行介绍。 ​ 硬件上我是用了正点原子核RT-Thread联合开发的潘多拉开发板,在本文中没有使用潘多拉的硬件,我比较偷懒的使用了开发板配套的例子去做逆向。 启动 ​ 我一直相信一句话,不会开发也就不会安全,开发能力决定着安全能力的天花板。在逆向STM32 & RT-Thread的过程中也是这个样子的。我们打开一个bin文件,第一件事就是找到main函数,这个main函数并不是stm32的main函数而是操作系统的main函数。例如在stm32 & keil开发中,RT-Thread使用 $Sub$$main 调用初始化操作系统,如果是不带操作系统的裸开发,这个函数就是逻辑的main函数了。 ​ 详细的启动过程可以在 https://www.rt-thread.org/document/site/tutorial

PHP-----浅谈垃圾回收机制

时光总嘲笑我的痴心妄想 提交于 2019-12-01 01:31:25
前言 大多数编程语言都会有自身的垃圾回收机制,php也不例外。经常听很多人说gc,也就是垃圾回收器,全程为Garbage Collection。 在php5.3之前,是不包括垃圾回收机制的,也没有专门的垃圾回收器,实现垃圾回收就是简单判断一下变量的zval的refcount是否为0,是的话就释放。 但是如果这么简单的判断垃圾回收的话,很容易引起程序过程中内存溢出。如果存在"自身指向自身"的情况的话,那么变量将无法回收早成内存泄露,所以从php5.3开始就出现了专门负责清理垃圾数据防止内存泄露的垃圾回收器。 引用计数的基本知识 我们要了解GC,那么首先要了解引起垃圾回收的基数是什么。 在php中,每个变量存在一个叫“zval”的变量容器中。一个zval变量容器,除了包含变量的类型和值,还包括另外两个字节的额外信息。第一个是"is_ref"。第二个是"refcount"。 is_ref是一个布尔类型的值,用来标示这个变量是否属于引用集合。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过"&"来使用自定义的引用,所以zval中还有一个内部引用计数机制,来进行优化内存。 refcount用来表示这个zval变量容器的变量的个数。所有符号存在一个符号表当中,每个符号都有作用域。 通俗的讲: 1、 refcount就是多少个变量是一样的用了相同的值

IDA 与VC 加载符号表

与世无争的帅哥 提交于 2019-11-29 05:32:47
将Windbg路径下的symsrv.yes 拷贝到ida 的安装目录,重新分析ntoskrnl.exe, 加载本地的符号表 添加环境变量 变量名:_NT_SYMBOL_PATH 变量值:SRV*{$Path}*http://msdl.microsoft.com/download/symbols/ 将“{$Path}”替换为要存储pdb符号表文件的路径,比如:C:\PDB,在线的符号下载。 于是用IDA,或者在VC里写程序调试时,都会从网上自动下载符号表…… msvcrt.pdb,ole32.pdb,System.Data.pdb,ws2_32.pdb,WebDev.WebServer.pdb…… 但是VC运行程序时会自动下载完所有要用到的pdb,所以第一次启动会很慢,若想立即看结果,只要把网络断开就行了…… 来源: http://www.cnblogs.com/lanrenxinxin/p/4513464.html

操作系统

孤街醉人 提交于 2019-11-28 21:35:18
C的内存分配 32bitCPU可寻址4G线性空间, 每个进程都有各自独立的4G逻辑地址, 其中0~3G是用户态空间, 3~4G是内核空间, 不同进程相同的逻辑地址会映射到不同的物理地址中. 其逻辑地址其划分如下: 正文段(code segment/text segment, .text段): 或称代码段, 通常是用来存放程序执行代码的一块内存区域. 这部分区域的大小在程序运行前就已经确定, 并且内存区域通常属于只读, 某些架构也允许代码段为可写, 即允许修改程序. 在代码段中, 也有可能包含一些只读的常数变量, 例如字符串常量等 . CPU执行的机器指令部分. ( 存放函数体的二进制代码 . ) 只读数据段(RO data, .rodata):只读数据段是程序使用的一些不会被改变的数据, 使用这些数据的方式类似查表式的操作, 由于这些变量不需要修改, 因此只需放在只读存储器中. 已初始化读写数据段(data segment, .data段):通常是用来存放程序中已初始化的全局变量的一块内存区域. 数据段属于静态内存分配. 常量字符串就是放在这里的, 程序结束后由系统释放(rodata—read only data). 已初始化读写数据段(RW data, .data):已初始化数据是在程序中声明, 并且具有初值的变量, 这些变量需要占用存储器空间,

符号表

寵の児 提交于 2019-11-28 18:32:42
符号表是一种存储键值对的数据结构,支持两种操作, - 插入(put) 将新的键值对存入表中 - 查询(get) 给定键得到相应的值 规则 重复的键 每一个键只能对应着一个值(表中不允许存在重复的键) 当存入的的键值对和表中已有的键冲突时,新的值会替代旧的值 空键 键不能为空,使用空键会产生一个运行异常。 空值 规定不允许有空值,当键不存在时get()返回空,任何不在表中的键关联的值都是空 删除操作 在表中删除有两种方法: 延迟删除 ,也就是将键对应的值置为空(null) put(key,null) 及时删除 ,delete(key) 实现 符号表分为有序和无序两种 无序链表的顺序查找 public class SequentialSearchST<K, V> { private class Node { K key; V val; Node next; public Node(K key, V val, Node next) { this.key = key; this.val = val; this.next = next; } } private Node first; public V get(K key) { for (Node x = first; x != null; x = x.next) { if (key.equals(x.key)) { return x.val