CSAPP-BinaryBomb实验

2023-11-10

目录

一、实验目的与要求

二、实验原理与内容

三、实验过程与结果

1、程序编码——汇编

2、拆解过程

Phase_1

Phase_2

Phase_3  

Phase_4

Phase_5

Phase_6

Secret_phase


一、实验目的与要求

1. 增强对于程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。

2. 掌握使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。

3. 需要拆除尽可能多的炸弹。

4. 建议在linux下进行文本拆弹密码文本编辑。

5. 建议使用gdb或IDA、edb、DDD之类的调试软件辅助进行。

6. 建议实验过程中手绘图表辅助逆向工程分析。

二、实验原理与内容

一个“binary bombs”(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了7个阶段(phase1~phase6和一个隐藏阶段)。炸弹运行的每个阶段要求学生输入一个特定的字符串,若的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出 "BOOM!!!"字样。实验的目标是拆除尽可能多的炸弹层次。

每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增: 

  1. 阶段1:字符串比较
  2. 阶段2:for循环
  3. 阶段3:switch分支
  4. 阶段4:递归函数
  5. 阶段5:数组元素按序访问
  6. 阶段6:链表
  7. 隐藏阶段:只有在阶段4的拆解字符串后再附加一特定字符串后才会出现(作为最后一个阶段)

为了完成二进制炸弹拆除任务,需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。这可能需要在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。

在调试程序时直接使用输入重定向指令,例如(假设密码已被写入到之前的拆弹密码文本文件solution.txt中):

./bomb < solution.txt

通过执行以上指令即可直接根据屏幕输出来判断程序正确地进行了几个阶段或者在第几个阶段出现了错误。如果密码全部正确,提示结果如下图所示:

三、实验过程与结果

基于实验原理和内容,结合本次实验的目的与要求,具体将此次实验分为以下四个步骤:

Step1:将可执行文件进行反编译,便于后续对实验的深入解答;

图1:objdump反汇编

Step2:阅读并理解汇编语言。基于bomb.c文件中的注释,可以发现这个“炸弹”的设计思路,一共分为了phase_1~6六个阶段以及隐藏阶段来“引爆炸弹”,只有正确输入密钥,才能拆解。同时结合Step1所得到的汇编文件对整个“炸弹”的设计有了初步的理解及拆解思路;

图2:bomb.c部分注释

图3:bomb.s文件初步思路

Step3:结合对汇编语言的理解,初始化对应拆解密钥;

图4:初始化两个阶段拆弹密码

Step4:使用gdb调试工具,快捷解析拆弹密码。

基于各炸弹的安置,逆向思维使用gdb调试 工具找出炸弹爆破点,从而倒推出密钥。gdb调试相关操作如下:

(1)设置断点,例如可以设为某个阶段的开始     

      break phase_1(或者 b phase_1)

(2)run  < soulution.txt (注意,这里是<号,不要写成大于号,否则输出的内容会覆盖solution.txt文件);

(3)按ctrl+x+a打开可视化调试界面;

(4)使用layout asm、layout regs等指令,打开汇编、寄存器窗口;

(5)使用nexti指令,逐步调试;

(6)使用gdb x命令,查看内存的值。

1、程序编码——汇编

结合以上实验步骤,想要完成拆弹任务,就需要了解有关汇编的知识,包括不同寄存器和操作符的使用方法以及操作数格式,具体如下图5-1~12所示:

图5-1 整数寄存器。所有 16 个寄存器的低位部分都可以作为字节、字(16 位)、 双字(32 位)和四宇(64 位)数字来访问

图5-2 操作数格式。操作数可以表示立即数(常数)值、寄存器值或是来自内存的值。比例因子 s 必须是 1、2、4 或者 8

图5-3 简单的数据传送指令

图5-4 零扩展数据传送指令。这些指令以寄存器或内存地址作为源,以寄存器作为目的

图5-5 符号扩展数据传送指令。MOVS指令以寄存器或内存地址作为源,以寄存器 作为目的。cltq 指令只作用于寄存器eax和rax

图5-6 入栈和出栈指令

图5-7 整数算术操作。加载有效地址(leaq)指令通常用来执行简单的算术操作。其余的指令 是更加标准的一元或二元操作。我们用>> A 和>> 来分别表示算术右移和逻辑右移。 注意,这里的操作顺序与 ATT 格式的汇编代码中的相反

图5-8 特殊的算术操作。这些操作提供了有符号和无符号数的全 128 位乘法和除法。 一对寄存器 组成一个 128 位的八字

图5-9 比较和测试指令。这些指令不修改任何寄存器的值,只设置条件码

图5-10 SET 指令。每条指令根据条件码的某种组合,将一个字节设置为 0 或者 1。有些指令有“同义名”,也就是同一条机器指令有别的名字

图5-11 jump 指令。当跳转条件满足时,这些指令会跳转到一条带标号的目的地。有些指令有“同义名”, 也就是同一条机器指令的别名

图5-12 条件传送指令。当传送条件满足时,指令把源值 S 复制到目的及。有些指令是“同义名”,即同一条机器指令的不同名字

2、拆解过程

创建答案文本文件answer.txt,并任意填入7行字符串,对应phase_1~6与secret_phase的破解字符串。

图1:创建拆解文件

结合实验步骤step4,打开终端输入“gdb ./bomb”,即使用gdb对bomb程序进行调试,并打开可视化界面。

图2:gdb调试可视化


Phase_1

在gdb设置断点phase_1,并读入answer.txt文件,使用nexti(ni)指令,逐步调试,发现了爆炸点“explode_bomb”;

图3:phase_1调试出爆炸点

基于发现的爆炸点进行分析,发现爆炸点的跳转是通过strings_not_equal函数判定的返回值进行跳转。而%rsi的值与传入的第一行参数进行test比较,只有“jne”-不相等才会爆炸,因此我们查看参数%rsi中的值得到phase_1密钥“I turned the moon into something I call a Death Star”;

图4:分析爆炸点

结合以上分析修改answer.txt中phase_1的字符串,并验证运行,成功拆解phase_1。

图5:成功拆解phase_1


Phase_2

在gdb中设置断点phase_2并同样运行answer.txt,调试发现一个爆炸点在函数read_six_numbers运行比较后出现,因此考虑进入函数查明原因;

图6:phase_2发现一个爆炸点

打开bomb.s文件搜索read_six_numbers函数,发现该函数是通过调用函数__isoc99_sscanf@plt将输入的字符串按照特定的格式解析为六个整数,并将这些整数存储在内存中的特定位置。然后,它通过比较解析成功的整数数量与5的关系来判断输入是否有效。如果解析成功的整数数量“jle”-小于等于5,那么它会调用函数“explode_bomb”,表示输入不符合预期,触发炸弹爆炸。因此,我们需要改变输入的值为6个整数,来避开第一个爆破点。同时,我们至此才发现,上一个爆炸点其实是第二个爆炸点,是用于检测栈顶值是否为1,即如果数组第一个数不为1,则会(在即使有6个整数通过read_six_numbers函数第一个爆炸点情况下)触发第二个爆炸点(图6中爆炸点phase_2+45)。

图7:分析第一个爆破点函数并修改传参

如下图8为phase_2第三个爆炸点位置,对其是否被调用(引爆)进行分析发现,它在检查参数%eax以及0x4(%rbx)是否相等,如果不相等,则爆炸。因此分析两个参数,不难发现这是一个for循环:根据0x1248地址的语句“mov %rsp,%rbx”得出%rbx是密钥数组首地址,紧接着0x124b语句计算%rbx并加上0x14的地址,将结果存储到%rbp寄存器中,0x14即为5个整数的内存空间,在这里相当于存储密钥数组的第2-6个整数;从而0x124f语句跳转至0x1261语句,将%rbx的值传参至%eax并“add”-加一遍自身,再与0x4(%rbx)进行比较。即从第二个数字开始,循环比较后一个数字是否为前一个数字的两倍。

图8:phase_2第三个爆炸点分析

结合以上第三个爆炸点分析,再次修改answer.txt中phase_2的字符串为1,2,4,8,16,32, 并运行测试,成功拆解。

图9:成功拆解phase_2


Phase_3  

依然在gdb中设置断点,设置在phase_3并且运行程序,分析到第一个爆炸点,如下图10所示。发现与phase_2第一个爆炸点相同都是基于__isoc99_sscanf@plt函数的输出结果与0x1进行比较,而此次以是否为“jle”-小于或等于来跳转至第一个爆炸点。因此对0x5555555569ef/%rsi进行查看,使用x/s得知密钥要求为输入两个整数。

图10:分析到第一个爆炸点

修改answer.txt中phase_3的字符串为任意两个整数“6 6”,并重新运行查找下一个爆炸点,发现在语句“cmpl $0x7,(%rsp)”之后,爆炸直接原因是%rsp中的值大于7,这里%rsp即为我们输入的数字首地址,即我们输入的第一个数应该不大于7,才能避开第一个爆炸点。此处我们无需修改。

图11:分析到第二个爆炸点

继续运行,发现了新的爆炸点phase_3+140,而语句“cmpl $0x5,(%rsp)”,等价于第二个爆炸点,需要限制栈顶的值不大于5。更为重要的是下一个语句“cmp %eax,0x4(%rsp)”,是比较%eax参数与我们传参的第二个整数进行比较,如果“je”-相等则跳转至其他位置,不相等同样会引爆第三个爆炸点。因此我们倒推会如图12中地址0x12c4的位置,不难发现这是基于栈顶的值来将“%rdx+%rax*4”地址处的值扩展为64位,并将结果与%rdx相加存储到%rax中,实现*%rax的跳转,并修改%eax的值为0。因此第二个整数的值应该为0。

图12:分析到第三个爆炸点phase_3+140

结合以上分析最终修改answer.txt中phase_3的字符串为“4 0”,重新运行检验,成功拆解。

图13:成功拆解phase_3


Phase_4

在gdb设置断点phase_4并且运行程序,发现第一个爆炸点与phase_3类似,使用x/s指令查看输入需求,发现也是检测是否传参为两个整数来引爆炸弹,并且phase4+45句也同样限制栈顶值是否“jbe”-小于等于0xe,如果不然则也会引爆炸弹。因此修改字符串为任意两个整数,并且第一个整数小于14(0xe)来通过第一个爆炸点。

图14:phase_4第一个爆炸点

排除第一个爆破点后,重新运行程序,定位到第二个爆炸点,对其进行分析发现:分别将14、0和栈顶值赋值给%edx,%esi,%edi然后传入func4函数,比较输出结果和15(0xf)的值如果不相等则引爆炸弹,如果相等则再检测第二个参数的值是否等于15(0xf),同样也会引爆炸弹。因此,考虑进入func4函数来解析返回值%eax。

图15:分析第二个爆破点

进入func4函数,查看汇编发现这是一个递归函数,通过累加来得到返回值,如下图为对应的汇编及对应伪代码。

图16:分析func4函数

结合代码分析,这是一个递归并累加%ebx的函数,我们需要得到%eax返回值为15。因为不同栈顶值会影响累加值,通过遍历不同阶段来确定是需要以下两次比较后的累加7+3+5才可以得到我们要的值,所以确定传入的edi(栈顶值)为5,从而修改密钥两个参数分别为“5 15”。

阶段/参数

edi

esi

edx

eax

ebx

初始

栈顶值

0

14

14

7

ebx>edi

栈顶值

0

6

6

3

ebx<edi

栈顶值

4

6

2

5

修改完answer.txt后运行检测,成功拆解phase_4。

图17:成功拆解phase_4


Phase_5

在gdb设置断点phase_5,并运行程序找到第一个爆炸点,分析发现同phase_3~4的第一个爆炸点相同,都是检测是否传参为两个整数,因此修改answer.txt中phase_5的字符串为任意两个整数。数。 

图18:分析phase_5第一个爆炸点

修改完重新运行程序,发现第二个爆炸点,分析得到:爆炸的原因是%edx不等于15(0xf),深入探讨发现了%edi是一个计数器,我们需要执行15次“add $0x1,%edx”,并基于跳转目标(地址为phase_5+76~89)的代码发现,跳转条件为%eax不等于15。且我们发现:phase_5+45中我们输入的参数%rsp赋值给%eax,并取出低四位,若%eax的值不等于15(地址phase_5+57),则也会进入爆炸点。而地址phase_5+81中可以发现%rax*4+%rsi值会赋给%eax,因此我们需要查看%rsi的值。

图19:分析第二个爆炸点

 图20:%rsi数组

结合以上分析,查看%rsi的值发现,这是一个数组,为了按序访问并得到返回值为15,从数值15进行15轮反推:

15->6->14->2->1->10->0->8->4->9->13->11->7->3->12->5

具体数组如下,因此%rax第一次应该为5,即第一个传参为5。

地址

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

10

2

14

7

8

12

15

11

0

4

1

13

3

9

6

5

完成对第一个参数的修改并重新运行调试,定位到新的爆炸点,分析得到爆炸的原因是%ecx和第二个参数不相等,引爆了炸弹。因此我们查看%ecx的值来得到密钥“115”。

图21:分析最后一个爆炸点

修改answer.txt中phase_5的字符串为“5 115”并重新运行程序,成功拆解。

图22:成功拆解phase_5


Phase_6

在gdb设置断点phase_6并调试程序,定位到第一个爆炸点,同phase_2一样需要我们输入6个数字,因此修改传参为6个任意数字。

图23:phase_6第一个爆炸点

重新运行程序,定位到新的爆炸点(依然是跳转到phase_6+45)。爆炸的直接原因是%eax的值“ja”-大于5,而%eax的值由%r12的值减去1得到。因此先查看%r12的值,发现这是我们输入的参数的首地址。而phase_6+78地址中代表%r12往后移四个字节,即我们输入的下一个数字,回看图23地址phase6_52的语句查看有关的跳转代码,发现此处是对%ebx进行计数,当%ebx超过5便执行phase_6+45即引爆语句。

图24:分析第二个爆炸点

基于上述分析继续查看相关%ebx的代码,发现如下phase_6+107处有关%r13d的代码,回推发现这也是一个计数参数,跳出的条件为值等于6的时候。回看图23地址phase6_37的语句易得%r13d的初始值为0。因此%r13是1到5的遍历,每次遍历都会将值赋给%ebx进行%ebx->5的遍历,因此会执行五次“add $0x4,%r12”,即比较我们输入的每个数字减去1的无符号结果是否小于等于5,从而得到新的参数要求为数字须是1-6,因此暂不用修改。 

图25:%r13d

继续运行,找到了新的爆炸点,分析得到爆炸原因是%eax与0x0(%rbp)的值相等,没有跳转,所以引爆。根据前文%rbp=%r12,而%eax的值为%rax*4+%rsp,又因为phase_6+60中%rax=%ebx,所以分析%rsp的值,发现这是我们输入参数的地址。结合上述分析可知,这一段代码会遍历传参数组的前后数字,如果重复则引爆。由于我们传入的是“1 2 3 4 5 6”因此也暂不需要更改。 

图26:分析新的爆炸点

继续运行,找到了第四个爆炸点:

图27:发现第四个爆炸点

分析第四个爆炸点,发现直接原因是%rbx的值没有“jle”-大于%eax的值,因此查看地址phase_6+167中%rbx的相关代码,并由+123处句可以看出%rbx与0x20(%rsp)有关,从而ni到+146处发现%rdx是由<node1>的操作得到,因此我们查看他的值发现是一个链表,存储了6个节点,这6个节点的值分别是1-0x212;2-0x369;3-0x04f;4-0x170;5-0x0ee;6-0x3d5,并且初始的链接顺序为:

node1->node2->node3->node4->node5->node6->NULL 

图28:分析第四个爆炸点

继续分析第四个爆炸点,可以发现地址phase_6+112~121处表示,%rdx是链表的节点,0x8(%rdx)的值是链表的下一节点的地址。而作为计数的%eax不等于%ecx时就执行+112语句。即寻找到链表节点并执行+123处语句;phase_6+123处语句将取出的节点地址放到0x20(%rsp,%rsi,8)的位置并且%rsi计数加一,当%rsi到达6时,执行到语句phase_6+138;作为传参首地址的%rsp,+138语句处为取出第%rsi+1个参数放到%ecx中,并设%eax值为1,将%rdx设为链表节点1的地址,如果%ecx大于1则返回语句phase_6+112,否则返回phase_6+123。phase_6+160语句是将%esi设置为0,并执行语句phase_6+138。综上所述,这一段代码phase_6+112~165处功能是为将6个链表节点按照我们输入参数的编号存储到0x20(%rsp)的位置。因此查看有关0x20(%rsp)的代码:发现这是根据我们输入的节点顺序来重新排列链表。%rbx为重排后链表的头节点。

图29:分析phase_6+112~165处代码功能

图30:分析0x20(%rsp)

而%eax为当前节点的下一个节点地址,因此我们需要的链表是节点值从小到大排序的链表。由于3-04f<5-0ee<4-170<1-212<2-369<6-3d5所以我们应该输入的参数为“3 5 4 1 2 6”。修改密钥并成功拆解。

图31:成功拆解phase_6


Secret_phase

secret_phase是隐藏了入口的,所以我们需要查看入口所在的地址,再拆除炸弹。查看bomb.s反汇编代码,搜索发现入口在phase_defused函数之中,于是在gdb中对该函数进行调试。

图32:找到secret入口

在gdb中设置断点phase_defused并运行程序,直到该函数执行6次会跳转+50位置的语句,转折点在此phase_defused+84~87,这里需要我们%eax的值等于3才可以抵达secret_phase的位置,因此我们查看两个地址所对应的参数要求,发现是需要我们输入两个整数和一个字符串,并且“5 15”是phase_4的密钥,因此我们在phase_4处增加一个任意的字符串。

图33:发现入口密钥

修改完后重新运行程序,定位到新的转折点分析跳转原因。在phase_defused+122语句,是比较%rdi和%rsi两个参数是否“jne”-不相等,x/s分别查看两个参数的值发现,%rdi是我们添加在密钥后的字符串,所以我们需要修改密钥为“DrEvil”。

图34:成功找到隐藏关钥匙

对通关密钥进行修改后运行程序,成功进入了secret_phase,设置断点开始拆解,同样是运行程序并找到了第一个爆炸点。分析这个爆炸点,发现是因为%eax无符号值大于1000(0x3e8)。而%eax是%rax的值减1,查看+24行的%rax,发现这是我们的输入值,因此得出限制设定:我们只能输入1-1000的数字。

图35:获取新限制

修改secret_phase的字符串为1-1000的任意值并重新运行程序,定位到第二个爆炸点,分析得:fun7函数的返回值%eax不“je”-等于4,所以没有跳转并引爆。因此打开fun7函数进行查看。

图36:分析第二个爆炸点 

首先分析fun7的参数%esi和%rdi,查看%esi发现是我们输入的数字。而%rdi是一个结构,其中储存了数据以及两个地址,通过后续分析发现是二叉树结构。

图37:fun7参数

对图36中fun7的代码进行分析发现:函数的终止有两处。第一是15cc和15cf语句,判断是否为空,如果为空则将0xffffffff赋值给%eax并结束函数;二是15d1~15e8语句段,是连个跳转语句,分别判断模块1:左子树(%edx>%esi)和模块2:右子树(%edx≠%esi)。我们需要得到返回值%eax=4,因此不能走第一部分的终止,因此我们需要%edx<=%esi,而%edx的值是为%rdi节点存储的数据,所以我们需要输入的%esi的值应该是二叉树某个节点的数据。为此我们需要执行一次模块2,将%eax值从0->1;再执行两次模块1来实现返回值为2。我们查询节点数值,由于是递归调用需要逆推,所以先执行两次左子树,再取差值得到答案“7”。

图38:二叉树结构数组

最后修改secret_phase的字符串为7,运行程序,成功拆解,完成整个系列炸弹拆解。

图39:成功拆解所有炸弹

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CSAPP-BinaryBomb实验 的相关文章

随机推荐

  • 批量下载百度搜索图片+labelimg制作自己的数据集+转换至Yolo-v5训练数据集

    由于课题需要 需要自己制作数据集进行训练 目前是自己制作的第二个数据集 发现有某些细节已经忘记 记录备忘 同时为后来者提供借鉴 文章以car tank数据集做为例子介绍 整体流程 1 准备数据 从各种途径获取原始数据 博主的car tank
  • 高德地图报错TypeError: undefined is not a constructor

    高德地图在开发聚合和路线规划时报错TypeError undefined is not a constructor evaluating new n Driving map pe found in 经排查 原因是没有引入对应的插件 我们来看
  • IntelliJ IDEA流行的构建工具——Gradle

    IntelliJ IDEA 是java编程语言开发的集成环境 IntelliJ在业界被公认为最好的java开发工具 尤其在智能代码助手 代码自动提示 重构 JavaEE支持 各类版本工具 git svn等 JUnit CVS整合 代码分析
  • 猿如意 Chatgpt的使用规则

    猿如意 Chatgpt 是一种自然语言生成模型 它可以用来自动生成文本内容 使用规则如下 启动猿如意 Chatgpt 模型 输入自然语言文本作为模型的输入 根据模型的输出生成文本内容 可以根据需要修改输入文本或调整模型的参数来得到不同的输出
  • pandas逐行/列 遍历Dataframe的三种方式

    目录 一 pandas DataFrame iterrows 二 pandas DataFrame itertuples 三 pandas DataFrame items pandas 逐行 逐列 遍历数据有以下三种方法 一 pandas
  • Qt学习总结(一)

    一 项目中遇到的问题 1 c 文件中不同类如何共用一个变量 头文件1 h 源文件1 cpp 其他源文件2 cpp 3 cpp这些源文件都包含头文件1 h 方法 在1 h声明全局变量 extern int n 在1 cpp定义该全局变量 in
  • golang性能分析,pprof的使用,graphviz,火焰图

    golang中的pprof的使用 graphviz 一 关于pprof包 go中有pprof包来做代码的性能监控 包括 cpu profile mem profile block profile 在两个地方有包 net http pprof
  • 中文医疗大模型汇总

    写在前面 随着大语言模型的发展 越来越多的垂直领域的LLM发不出来 针对医学这一垂直领域的LLM进行整理 放在这里 希望对大家有一定的帮助吧 还会继续更新 大家有兴趣的话可以持续关注 更多关于中文医疗自然语言处理的资源和论文汇总 请访问我的
  • GoLang学习资源清单

    地鼠文档go语言文档网站通过收集整理go语言相关的学习文档 为大家提供一个学习平台https www topgoer cn 前景 Go语言中文文档https www topgoer com 文档 Gin Web FrameworkGin W
  • pyinstaller 打包.py文件生成exe(含转换.py文件为.pyd,保护源码,适合发布程序or论文复现用)

    文章目录 操作详情 1 安装Cython 2 修改调用外部数据or文件的 py文件 4 在命令行运行python setup py build ext inplace 5 创建main py文件 import 所有用到的包 写一个main
  • 数据库分表策略

    1 垂直划分 将数据表中的某些字段提出 组成新的数据表 将群组id 专辑id 音乐id提出 组成gzm数据表 而将 群组 专辑 音乐的详细信息单独放在其他数据表中 在求取索引 关系时 操作数据库效率更高 2 水平划分 2 1物理上的水平切分
  • 2018蓝桥杯B组国赛

    1 标题 三角形面积 已知三角形三个顶点在直角坐标系下的坐标分别为 2 3 2 5 6 4 3 1 5 1 7 2 求该三角形的面积 注意 要提交的是一个小数形式表示的浮点数 要求精确到小数后3位 如不足3位 需要补零 思路 利用两点求距离
  • vue项目(vue-cli)配置环境变量和打包时区分开发、测试、生产环境

    1 打包时区分不同环境 在自定义配置Vue cli 的过程中 想分别通过 env development env test env production 来代表开发 测试 生产环境 NODE ENV development NODE ENV
  • 坐标转换WGS-84 转 GCJ-02 和 GCJ-02转WGS-84

    WGS 84 to GCJ 02 static wgs gcj lng lat if this out of china lng lat return lng lat else var a 6378245 0 a 卫星椭球坐标投影到平面地图
  • ros系统设置动态服务器,让ROS变成你量身定做的WEB服务器

    如何用ROS来做一台简单的WEB服务器 我也提供了一些思路 但都太过于复杂 难以实用 介绍一种比较简单的修改方法 把HTTP目录链接到FTP目录下 不就可以很方便的修改了吗 试验 马上行动测试一下 1 关闭ROS 我的是学习用的 可一说关就
  • 15、OpenCV形态学操作——Hit-or-Miss

    OpenCV形态学操作 Hit or Miss 一 学习目标 二 Hit or Miss 一 学习目标 理解什么是Hit or Miss 学会在OpenCV中使用Hit or Miss 二 Hit or Miss 形态学算子根据图像的形状来
  • ceph集群部署

    一 ceph特点高性能 1 摒弃了传统的集中式存储元数据寻址的方案 采用CRUSH算法 数据分布均衡 并行度高 2 考虑了容灾域的隔离 能够实现各类负载的副本放置规则 例如跨机房 机架 感知等 3 能够支持上千个存储节点的规模 支持TB到P
  • vue上线项目去除所有console.log打印日志

    第一步 安装 babel plugin transform remove console 开发依赖 方法一 npm i babel plugin transform remove console save dev 方法二 第二步 在babe
  • 【数据库MySql】数据库基础——库和表的基础操作

    数据库学习大纲 1 SQL编程语言的语法 核心 2 数据库内部原理 面试题 3 使用java代码操纵数据库 JDBC编程 SQL是一个专门用来操作数据库数据的编程语言 MySQL服务器里面里有很多个数据库 这些是逻辑上的数据集合 一个数据库
  • CSAPP-BinaryBomb实验

    目录 一 实验目的与要求 二 实验原理与内容 三 实验过程与结果 1 程序编码 汇编 2 拆解过程 Phase 1 Phase 2 Phase 3 Phase 4 Phase 5 Phase 6 Secret phase 一 实验目的与要求