-
路由器固件
2018-09-10 15:48:20路由器固件 修改射频参数,修改优化界面,添加更多个性化管理 -
E1路由器固件
2019-01-17 22:28:27e1路由器固件. -
网件路由器固件
2019-02-16 17:06:26网件路由器固件 额 -
tplink路由器怎么升级固件? tplink更新路由器固件的技巧
2020-10-02 01:30:04tplink路由器怎么升级固件?路由器想要升级一下固件,该怎么升级呢?今天我们就以tplink路由器为例教大家升级路由器固件的方法,需要的朋友可以参考下 -
捷稀路由器固件
2014-10-04 20:46:50无线路由器固件 -
ar9344路由器固件
2018-01-25 17:57:25ar9344路由器固件 -
JCG Q7路由器固件
2018-10-14 02:59:17JCG Q7路由器固件,用于系统恢复、降级、升级,稳定版 -
潘多拉路由器固件备份.docx
2021-02-16 22:18:52潘多拉路由器固件备份.docx -
路由器固件解析
2021-01-19 22:40:18路由器固件解析 简要题意 现在的路由器事实上跑的都是嵌入式Linux,所谓固件,就是Linux系统保存在芯片中的一个镜像。现在请你找一个路由器的固件,对它进行分析,要求: - 能解析出这个固件内的文件系统,展示整个...简要题意
现在的路由器事实上跑的都是嵌入式Linux,所谓固件,就是Linux系统保存在芯片中的一个镜像。现在请你找一个路由器的固件,对它进行分析,要求:
- 能解析出这个固件内的文件系统,展示整个目录树;
- 能够导出其中特定的文件或目录;
- 能够把固件中的root口令清除前期分析
我们需要解析的固件是一个bin文件,因此我们首先的思路就是通过winhex工具打开
winhex
windows下的16进制编辑器winhex打开固件后,我们可以看到某些数据段是可以直接通过ascll码看出的,比如如下固件就是一个斐讯的路由器固件
我们知道,linux固件中常用的为cramfs和squashfs两个文件系统
cramfs ---- 头部特征字符为"0x28cd3d45"
squashfs ---- 头部特征有sqsh、hsqs、qshs、shsq、hsqt、tqsh、sqlz 7种
在winhex中尝试搜索一些头部特征,我们发现只有hsqs是可以被发现的,因此我们猜测这个文件系统是Squashfs并且文件头是hsqs
因此我们可以通过hexdump命令确定该文件系统头部偏移接着我们用dd命令将该块数据前一百个字节复制出来,来查看squashfs文件系统的头部检验
在这里看到了一些具体的信息,想要获取进一步的信息,我们也可以通过binwalk进行分析
在这里可以看到开头是一些CRC32检验码,来检验程序的正确性,接下去是一些uImage信息,再接下去可以看到许多数据是被进行了LZMA压缩,并且同时也可以看到Squashfs的大小和块的信息。
我们通过尝试发现在文件尾部加入其他垃圾数据并不影响文件正常运行,因此在提取文件系统的时候,我们可以直接通过搜索hsqs信息,定位开头,直接写到结尾就为文件系统了。对于清除root,思路如下:(Tip:代码中未实现)
在Linux系统中,/etc/shadow 文件,用于存储 Linux 系统中用户的密码信息,又称为“影子文件”
我们可以找到shadow文件在固件中的地址,将其解压然后删除密码再压缩而Squashfs中fragments块实际上是储存了每个文件的首地址及其大小的,因此这对于我们定位shadow文件很关键
因此,我们应该如何获取fragment信息呢?
这里需要介绍一个库PySquashfsImagePySquashfsImage
This package provides a way to read and extract squashfs images.我们查看他的库源代码,发现read_fragment()函数中获得了shadow文件相应的fragment
接着输出可以得到shadow文件在文件系统中的偏移为3006730 大小为19956
同时可以计算知道他在固件文件中的地址 = 0x2CB70A + 0x2DE10A
接下去就可以将其替代掉,并通过lzma重新压缩回去,但可能字节数和某些信息也同时变动了,因此检验时出错导致bin文件崩溃,因此我们离清除root还是遇到了一些问题。
而对于图形化,目录树是由PyQt5中QTreeWidget树型控件实现的,其他是python自带的gui——tkinter。对于Squashfs的读写是通过PySquashfsImage库实现的
程序部分截图如下:
代码实现
import sys import windnd from PySquashfsImage import SquashFsImage from PyQt5.QtWidgets import * from PyQt5.QtGui import QIcon, QBrush, QColor from PyQt5.QtCore import Qt import tkinter as tk import tkinter.messagebox import pickle import os import time list=[] dict={} #global address menu =tk.Tk() menu.title('Squash工具') menu.geometry('600x500') l1 = tk.Label(menu, text='欢迎来到Squashfs解析工具!', width=100, height=3) l1.pack() tk.Label(menu,text='设置需要分析的固件地址:').place(x=10, y=100) var_add = tk.StringVar() mulu_var = tk.StringVar() entry_add = tk.Entry(menu,textvariable=var_add,width=20) entry_add.place(x=270,y=100) entry_muluget = tk.Entry(menu,textvariable=mulu_var,width=20) entry_muluget.place(x=135,y=250) tk.Label(menu,text='输入目录:').place(x=30, y=250) tk.Label(menu, text='导出进度:', ).place(x=30, y=300) canvas = tk.Canvas(menu, width=400, height=22, bg="white") canvas.place(x=130, y=300) fill_line = canvas.create_rectangle(1.5, 1.5, 0, 22, width=0, fill="green") global now_x now_x=0 global number number=1 def init(): #print('请输入固件地址:') global address address=var_add.get() #tkinter.messagebox.showinfo(title='Welcome', message=address) extractSquashFs(address) address='kernel.squash' tkinter.messagebox.showinfo(title='Welcome', message='设置地址成功!') #address=input()#C:/Users/dylolorz/Desktop/py/kernel.squash image = SquashFsImage(address) p=1 for i in image.root.findAllPaths(): b=i.split('/') list.append(b[1:]) image.close()#读入文件路径 def dro(files): msg='\n'.join((p.decode('gbk') for p in files)) #tkinter.messagebox.showinfo(title='Welcome', message=msg) entry_add.delete(0,200) entry_add.insert (0,msg) class TreeWidgetDemo(QMainWindow): def __init__(self, parent=None): super(TreeWidgetDemo, self).__init__(parent) self.setWindowTitle('Squashfilesystem') self.tree=QTreeWidget() #设置列数 self.tree.setColumnCount(1) #设置树形控件头部的标题 self.tree.setHeaderLabels(['Name']) #设置根节点 root=QTreeWidgetItem(self.tree) root.setText(0,'Squash') #root.setIcon(0,QIcon('./images/root.png')) #设置树形控件的列的宽度 self.tree.setColumnWidth(200,1000) # for i in range(1,len(list)): if(len(list[i])==1): str=list[i][0] now=QTreeWidgetItem(root) now.setText(0,str) root.addChild(now) dict[str]=now for i in range(1,len(list)): if(len(list[i])>1): str=list[i][-1] str1=list[i][-2] fa=dict[str1] now=QTreeWidgetItem(fa) now.setText(0,str) fa.addChild(now) dict[str]=now #加载根节点的所有属性与子控件 self.tree.addTopLevelItem(root) self.setCentralWidget(self.tree) def fun1(): app = QApplication(sys.argv) tree = TreeWidgetDemo() tree.show() app.exec_() #sys.exit(app.exec_()) def fun2_1(): print('请输入导出目录:') to_add=input() print('请输入你需要导出的文件名称,例如:ResponsiveMadCapLogo.png') str=input() image = SquashFsImage(address) for i in image.root.findAll(): if i.getName() == str.encode(encoding='utf-8'): with open(to_add.encode(encoding='utf-8')+i.getName(),'wb') as f: print(i.getName()+b' Sucessful!') f.write(i.getContent()) image.close() def extractFile(fileName): ''' 提取单个文件并保存再相应的位置 fileName 格式为 /xxx/xxx/filename 保存的位置为当前运行目录下 */xxx/xxx/filename 中 ''' image = SquashFsImage(address) # 提取单个文件并保存再相应的位置 for i in image.root.findAll(): if i.getName() == fileName.split('/')[-1].encode("utf-8"): print("/".join(fileName.split('/')[1:])) with open("/".join(fileName.split('/')[1:]),'wb') as f: print("file",'"'+i.getName().decode("utf-8")+'"','extract success ') f.write(i.getContent()) image.close() def extractDir(): ''' 提取特定目录 dirPath 为squashfs中的特定目录 格式 /xxx/ 为提取主目录中xxx文件夹下的所有内容 ''' dirPath=mulu_var.get() image = SquashFsImage(address) dir_list = [] # 存所有文件的目录 imageall = [] # 存image.root.finAll中符合条件的元素 # 创建根目录 if os.path.exists("/".join(dirPath.split('/')[1:-1])) == False: os.makedirs("/".join(dirPath.split('/')[1:-1])) #从image.root.findAll的返回值中筛选符合条件的数据 for i in image.root.findAll(): if dirPath in i.getPath() and i.getPath().split(dirPath)[0] == '': imageall.append(i) dir_list.append(i.getPath()) global number global now_x now_x=400/number fill_line = canvas.create_rectangle(1.5, 1.5, 0, 22, width=0, fill="green") # 对所有筛选出的文件或文件夹进行处理 若为文件则提取 若为文件夹则创建 for item in dir_list: name = item.split('/')[-1].encode("utf-8") dirpath = "/".join(item.split('/')[1:]) for i in imageall: if i.getName() == name: if i.isFolder(): if os.path.exists(dirpath) == False: os.makedirs(dirpath) else: extractFile(item) now_x=now_x+400/number #print(now_x) canvas.coords(fill_line, (0, 0, now_x, 60)) menu.update() #print('now_x=',now_x) image.close() tkinter.messagebox.showinfo(title='Welcome', message='获取成功!!') def extractDir1(): ''' 提取特定目录 dirPath 为squashfs中的特定目录 格式 /xxx/ 为提取主目录中xxx文件夹下的所有内容 ''' dirPath=mulu_var.get() image = SquashFsImage(address) dir_list = [] # 存所有文件的目录 imageall = [] # 存image.root.finAll中符合条件的元素 # 创建根目录 if os.path.exists("/".join(dirPath.split('/')[1:-1])) == False: os.makedirs("/".join(dirPath.split('/')[1:-1])) #从image.root.findAll的返回值中筛选符合条件的数据 for i in image.root.findAll(): if dirPath in i.getPath() and i.getPath().split(dirPath)[0] == '': imageall.append(i) dir_list.append(i.getPath()) global number # 对所有筛选出的文件或文件夹进行处理 若为文件则提取 若为文件夹则创建 for item in dir_list: name = item.split('/')[-1].encode("utf-8") dirpath = "/".join(item.split('/')[1:]) for i in imageall: if i.getName() == name: number=number+1 image.close() def Search(string,pattern): ''' 查找hsqs再bin文件中的位置 ''' for i in range(len(string)): if string[i] == pattern[0]: flag = True for j in range(len(pattern)): if string[i+j] != pattern[j]: flag = False break if flag == True: return i def extractSquashFs(firmware): ''' firmware为固件位置 比如C:\\Users\\liu11\\Desktop\\Pyfirmware\\K3C_V32.1.46.268.bin ''' squashdata = [] with open(firmware,"rb") as f: data = f.read() dataarray = bytearray(data) squash = "hsqs".encode("utf-8") index = Search(dataarray,squash) f.seek(index) squashdata = f.read() with open("kernel.squash","wb") as f: f.write(squashdata) def ac(): global number extractDir1() #print(number) extractDir() fill_line2 = canvas.create_rectangle(1.5, 1.5, 0, 22, width=0, fill="white") np=0 for i in range(number): np = np + 400 / number canvas.coords(fill_line2, (0, 0, np, 60)) menu.update() time.sleep(0) number=1 windnd.hook_dropfiles(menu,func=dro) bt1_addr = tk.Button(menu, text='确定', command=init) bt1_addr.place(x=500,y=100) bt2_mulu = tk.Button(menu, text='获取Squashfs目录树', command=fun1) bt2_mulu.place(x=190,y=180) bt3_mulu = tk.Button(menu, text='导出特定文件或者目录', command=ac) bt3_mulu.place(x=380,y=240) menu.mainloop()
-
好用的潘多拉7620路由器固件,挂卡固件
2018-04-17 22:19:37好用的潘多拉7620路由器固件,挂卡固件,支持各种网卡固件,支持16M以上闪存 -
路由器固件升级
2011-12-21 13:26:39一款路由器升级工具 ,可以快速升级路由器固件。 -
网件WNDR4300路由器固件
2015-12-20 23:42:11网件WNDR4300路由器固件 -
极壹s路由器固件修复工具 免费版
2020-07-12 15:40:34极壹s路由器固件修复工具是一款多功能路由器固件修复驱动,它能有效修复路由器无法正常上网等难题,路由器各项参数都可自定义设置,使用简单上网更流畅。快下载体验吧!软件介绍虽然很多人使用路由器都是一个固件... -
PandoraBox-路由器固件
2019-04-15 13:06:47路由器固件,具体哪个版本不清楚, 但是我用挂卡路由器刷过。没有变砖。如果有不死UB的同学可以闭着眼睛大胆刷吧,荣欣的挂卡路由也没问题,火星的挂卡同样可以。这个路由器的好处在哪里。 我说下这个路由器的固件,... -
路由器固件模拟环境搭建(超详细)
2021-01-06 06:15:09路由器固件模拟环境搭建 0X01 想说的话 -
Netgear JNR3210 路由器固件
2015-01-31 16:34:55Netgear JNR3210 路由器固件v1.1.0.29 -
ESP8266一秒变成中继路由器固件及教程
2020-04-12 23:57:01ESP8266一秒变成中继路由器固件及教程 -
小米路由器怎么升级固件?小米路由器固件升级教程
2020-10-01 20:22:04由于小米路由器今年才正式发布,还有很多功能并未完善,升级空间很大。那么小米路由器怎么升级固件?这里简单介绍下怎么为你的小米路由器升级固件的方法。一起来看看吧 -
修改TP路由器固件的小工具
2017-03-15 19:41:33修改TP路由器固件的小工具 -
华硕路由器固件地址
2019-08-10 16:12:40 -
padavan路由器固件设置ipv6拨号
2019-12-09 19:53:03 -
941n v5.1原厂路由器固件
2015-12-05 20:08:35941n v5.1原厂路由器固件,用编程器备份的 -
360安全路由无法升级固件?360安全路由器固件升级下载失败解决办法
2020-10-01 11:46:37才买的360路由器,想升级固件但每次都才升级了一点就显示升级失败了这可如何是好,360安全路由无法升级固件失败怎么办?本文为大家介绍可以解决360安全路由器固件升级失败的方法 -
思科WRVS4400Nv2企业无线官方路由器固件
2020-08-11 21:05:58思科WRVS4400Nv2企业无线官方路由器固件WRVS4400Nv2_v2.0.2.2,官方固件,英文版 -
路由器固件分析工具binwalk
2014-11-13 14:47:05路由器固件分析工具binwalk,可以看到固件头,rootfs的位置,文件系统,压缩算法等信息. 使用的时候先运行里面的deps.sh把依赖包装上再编译安装 -
思科wrh54g无线路由器固件
2015-07-14 17:28:13思科wrh54g无线路由器固件。经本人测试,可正常使用(不包括原厂的英文版固件)