0
点赞
收藏
分享

微信扫一扫

汇编学习记录-二进制炸弹-x86架构

前端王祖蓝 2022-04-21 阅读 42
开发语言

系列文章目录

第一章 汇编学习记录-二进制炸弹-x86架构
第二章 汇编学习记录-二进制炸弹-arm64架构
第三章 汇编学习记录-简单总结


文章目录


前言

学校课程计算机系统的实验二:二进制炸弹
这里记录一下破解过程
ps:答案仅供参考,拿走也没用,据老师说是根据我们的学号生成的


一、炸弹1

密码如下:I am for medical liability at the federal level.
破解过程:
在这里插入图片描述

方法中可以看到 我们将的返回值mov到%rdi中作为的参数

在这里插入图片描述
<phase_1>中另一个参数放入%esi并一起作为<strings_not_equal>的参数,我们可以知道该参数即为炸弹1的密码
接下来通过gdb来查看该参数,过程如下
在这里插入图片描述
在这里插入图片描述

二、炸弹2

密码如下:1 2 4 7 11 16
首项为一个非负数,后面+1,+2,+3……
破解过程:

在这里插入图片描述

首先看方法中,将<read_line>的返回值放入%rdi,充当参数
在这里插入图片描述

然后看<pharse_2>中,将栈指针先移动20字节,再将栈指针的值作为参数,传给<read_six_numbers>
在这里插入图片描述

在<read_six_numbers>中,我们读入了6个数,并放在<pharse_2>中开拓出的栈空间里
在这里插入图片描述
回到<pharse_2>中,接下来是一个循环,用c语言表示大致为

int ebx = 1;
do{
	if(ebx>5)break;
	rax=ebx;
	edx=rbx-1;
	rdx=edx;
	ecx=ebx;
	ecx+=M[rsp+4*rdx];
	ebx++;
}while((M[rsp+4*rax]-ecx)!=0);

将其简化,我们知道若M[rsp+4*ebx]-M[rsp+4*(ebx-1)]==0,则符合条件。
若将我们输入的数放在数组M中,那么其应该满足条件M[i-1]+i==M[i]

三、炸弹3

密码如下:
0 236或1 -509或2 28或3 -945或4 0或5 -945
破解过程:
在这里插入图片描述
在<pharse_3>中,可以看到将$0x40334f放到%esi中作为scanf函数的参数,所以我们可以知道这个代表密码的格式
在这里插入图片描述
通过gdb查看该字符出得到”%d %d”,可知密码是两个整数
在这里插入图片描述
由jmpq *0x4031c0(,%rax,8)知道这里是使用switch进行跳转。当读入的第一个数>7时,破解失败
在这里插入图片描述
在这里插入图片描述
通过gdb我们可以看到跳转表的内容
在这里插入图片描述
通过跳转表,我们可以对其进行标记并分析
当读入的第一个数为

又因为读入第一个数应<=5,排除后两个

四、炸弹4

密码如下:
176 2或264 3或352 4
破解过程:
在这里插入图片描述
首先我们查看要求输入的字符串格式
在这里插入图片描述
接下来,进入
在这里插入图片描述
将整理为类似c语言的形式

 fun4(edi, esi){
//若将edi中定为n,esi中定为x
	//若x<=0,返回0
	if(edi<=0)return 0;
	else{
		push r12,rbp,rbx;
		ebp = edi;
		ebx = esi;
		if(edi==1){
			//若n==1,返回x
			eax=esi;
			pop r12,rbp,rbx;
		}else{
		//构造fun4(n-1,x)
		edi--;
		fun4(edi,esi);
		//将返回值+x保存
		r12d=rax+rbx;
		//构造fun4(n-2,x)
		edi=rbp-2;
		esi=ebx;
		fun4(edi,esi);
		//将返回值加上之前保存的值
		eax+=r12d;
		pop r12,rbp,rbx;
		//返回fun4(n-1,x)+x+ fun4(n-2,x)
		return rax;
		}
	}
}

进一步整理得到

int fun4(int n, int x){
	if(n<=0)return 0;
	else{
		if(n==1)return x;
		else{
			return fun4(n-1,x)+fun4(n-2,x)+x;
		}
	}
}

容易知道当n(%edi)=9时,fun4最终返回的值为88*x(%esi)
在这里插入图片描述
回到<pharse_4>,可知输入的第1个数应为第2个数的88倍,且第2个数应为2、3、4

五、炸弹5

密码如下:
5 115
破解过程:
在这里插入图片描述
先看输入答案的格式,为两个整数
在这里插入图片描述
这段代码大致有几个过程
将输入的第1个数对16求模
进入循环
将读入第1个数求模后记为x1,第2个数记为x2
则循环可写成

edx =0;
ecx=0;
while(x1!=15){
	x1=M[x1];
	ecx+=x1;
}

在这里插入图片描述
其中M是一个数组,通过gdb可查看其中的值{a,2,e,7,8,c,f,b,0,4,1,d,3,9,6,5}
由简单的代入知道,若不停循环x1的值会形成一个不断重复的序列,a,1,2,e,6,f,5,c,3,7,b,d,9,4,8,0……
由后面条件知,若循环完成后,edx不为15,则会爆炸
那么x1只能在循环第15次时取f,所以x1的初始值应为5,同时经过简单的计算可知,此时ecx应为115,那么输入的第2个数也应该为115

六、炸弹6

密码如下:5 2 3 1 4 6
破解过程:
在这里插入图片描述
先读入6个数

在这里插入图片描述
接下来时一个循环,整理这个循环

ebp=0;
while(ebp<=5){
	eax=M[ebp];
	eax--;
	if(eax>5)call<explode_bomb>;
	r12d=rbp+1;
	ebx=r12d;
	while(ebx<=5){
		rax=ebp;
		rdx=ebx;
		edi=M[rdx];
		if(edi==M[rax]) call<explode_bomb>;
		ebx++;
	}
	ebp=r12d;
}

我们可以知道这个二重循环的作用是确保读入的6个数字全都不同
在这里插入图片描述
接下来还是循环

eax=0;
while(eax<=5){
	rcx=eax;
	edx=7;
	edx-=M[rcx];
	M[rcx]=edx;
	eax++;
}

这个循环是在将我们输入的每个数都对7求补,并放回原位
在这里插入图片描述
在这里插入图片描述

esi=0;
while(esi<=5){
	eax=1;
	edx=0x4052d0;
	rcx=esi;
	while(M[rcx]>eax){
		rdx=(rdx+8);
		eax++;
		rcx=esi;
	}
	rsp[rcx]=rdx;
	esi++;
}
rbx=(rsp);
rcx=rbx;

在这里插入图片描述
通过gdb我们知道0x4052d0指向一个链表
node1(0x39)->node2(0x3e5)->node3(0xc7)->node4(0x334)->node5(0x3ad)->node6(0xef)->null
这个循环的效果是将链表各节点的地址以数组中数的顺序放到栈中
在这里插入图片描述

eax=1;
while(eax<=5){
	rdx=eax;
	rdx=rsp[rdx];
	(rcx+8)=rdx;// rcx=(rsp);
	eax++;
	rcx=rdx;
}
(rcx+8)=0;

进一步简化

rcx=rsp[0];
eax=1;
while(eax<=5){
	rdx=rsp[eax];
	rcx->next=rdx;
	rcx=rdx;
	eax++;
}

这个循环,将链表的结点按照栈中的顺序重新连接;
在这里插入图片描述

ebp=0;
while(ebp<=4){
	rax=(rbx+8);// rbx=(rsp);
	eax=(rax);
	if((rbx)>=eax){
	rbx=(rbx+8);
	ebp++;
	}else call<explode_bomb>
}

进一步简化

ebp=0;
rbx=rsp[0]
while(ebp<=4){
	rax=rbx->next;
	eax=rax->num;
	if(rbx->num>=eax){
	rbx=rbx->next;
	ebp++;
	}else call<explode_bomb>
}

这个循环检测重新排列的链表是否按照降序排列
综上,我们应该将链表节点按照其中数字降序排序得到2 5 4 6 3 1,再对其与7求补,得到5 2 3 1 4 6

七、隐藏关

密码如下:7
破解过程:
在这里插入图片描述
先看<phase_defused>我们知道其与0x40576c处比较以决定是否跳转;
通过gdb查看该处的值
在这里插入图片描述
当输入字符串后,值发生变化
在这里插入图片描述
在这里插入图片描述
我们可以知道,当输入六个字符串时,该函数才会继续分析,才有可能进入<secret_pharse>
在这里插入图片描述
接下来,读入了三个值,且通过gdb可以看到其格式
在这里插入图片描述
格式为两个整数和一个字符串
查看0x405870处的值,
在输入第四个字符串前
在这里插入图片描述
在输入第四个字符串后
在这里插入图片描述
可以看到0x405870处保存了输入的第四个字符串的值,
在这里插入图片描述
接下来将读入的字符串与0x4033a2字符串进行比较
在这里插入图片描述
在这里插入图片描述
在检测完字符串后,会输出特定字符串,并且进入<secret_pharse>
综上,我们知道,在第四个炸弹输入密码时,在后面增加DrEvil,在完成六个炸弹后,即可进入<secret_pharse>

在这里插入图片描述
将0x4050f0作为参数传给了,用gdb查看0x4050f0
在这里插入图片描述
可以推测这里是一种二叉树
在这里插入图片描述

接下来进入,整理得到

fun7(rdi , esi){
	If(rdi==null){call<explode_bomb>}
	eax=rdi->num;
	if(eax>esi){
		rdi=rdi->lchild
		return 2*fun7(rdi , esi)
		
	}else if(eax <esi){
	rdi=rdi->rchild
	return 2*fun7(rdi , esi)+1
	}else return 0;
}

在这里插入图片描述
通过后面分析知道的返回值应该为4
我们算出
在这里插入图片描述
由此知道,密码应为7


举报

相关推荐

0 条评论