COM 进程注入技术

COM PROCESS INJECTION for RUST

项目地址:http://github.com/0xlane/com-process-inject

Process Injection via Component Object Model (COM) IRundown::DoCallback().

该技术由 @modexpblog 挖掘发现,在我对该技术进行深入研究过程中,将原项目 mdsecactivebreach/com_inject 使用了 Rust 重写,希望对使用 Rust 的安全人员在 COM 接口调用、进程注入等方面有所帮助。

对于此项注入技术原理的更保真的解释,还请参考 http://www.mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/,这里只记录一下工具用法和过程中遇到的一些问题和想法。

使用方法

PS D:\rust\com-inject> .\target\release\com-inject.exe -h
com-inject (1.0) - REInject
A process injection tool via COM
Commands:
  inject  Inject special dll or shellcode to target process
  list    List interface instance in special or all process
  help    Print this message or the help of the given subcommand(s)
Options:
  -h, --help     Print help
  -V, --version  Print version
#############################################################
PS D:\rust\com-inject> .\target\release\com-inject.exe inject -h
Inject special dll or shellcode to target process
Usage: com-inject.exe inject [OPTIONS] <PID>
Arguments:
  <PID>  Target process id
Options:
  -m, --method            Use CoGetObject instead of CoUnmarshalInterface to establish channel
  -d, --dll <PATH>        Inject DLL into target, specify full path
  -s, --shellcode <PATH>  Inject shellcode into target process
  -h, --help              Print help
#############################################################
PS D:\rust\com-inject> .\target\release\com-inject.exe list -h
List interface instance in special or all process
Usage: com-inject.exe list [OPTIONS] [PID]
Arguments:
  [PID]  Target process id
Options:
  -v, --verbose  Dispaly all interface, default only IRundown
  -h, --help     Print help

Tips:

  • DLL 和 Shellcode 文件路径使用绝对路径
  • 不论是 list 操作还是 inject 操作,都会尝试开启 DEBUG 权限
  • 避免对同一进程交替进行 DLL 注入和 shellcode 注入或者重复进行 DLL 注入,可能会报错 “被调用的对象已与其客户端断开连接。 (0x80010108)”,貌似是多次调用后远程接口会被释放掉
  • 如果报错 “不支持此接口 (0x80004002)”,就多试几遍
  • 并不是任何进程都能注入,只能对 list 动作显示出来的进程进行注入

技术原理

先说一下如何使用 Rust 对 COM 接口调用,调用过程可以分这几个步骤:

  1. 接口定义
  2. 调用 CoInitializeEx 初始化
  3. 调用 CoGetObject 或其他类似 API 获取接口指针
  4. 使用接口指针调用接口方法
  5. 调用 CoUninitialize 结束

重点在接口定义,后面几步都是 API 调用,对于一些有文档记录的接口一般都有对应的头文件或 IDL,直接用就行,但是对于其他 COM 接口,调用之前先要定义一个包含方法虚表的结构体/接口,这个虚表的内存偏移、方法顺序需要保证和接口实现一致,后面拿到接口指针才能正确调用对应的方法,c++ 里的接口定义示例:

const IID 
IID_IRundown = {
     0x00000134,
     0x0000,
     0x0000,
    {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
    
MIDL_INTERFACE("00000134-0000-0000-C000-000000000046")
IRundown : public IUnknown {
    STDMETHOD(RemQueryInterface)         ( REFIPID         ripid,
                                           ULONG           cRefs,
                                           USHORT          cIids,
                                           IID            *iids,
                                           REMQIRESULT   **ppQIResults);
                               
    STDMETHOD(RemAddRef)                 ( unsigned short  cInterfaceRefs,
                                           REMINTERFACEREF InterfaceRefs[],
                                           HRESULT        *pResults);
                               
    STDMETHOD(RemRelease)                ( USHORT          cInterfaceRefs,
                                           REMINTERFACEREF InterfaceRefs[]);
};

所有 COM 接口的祖先就是 IUnknown,大部分接口直接继承自 IUnknown,还有部分通过继承 IDispatch 或其他接口间接的继承自 IUnknown。继承在内存布局上实际上就是在父类的内存结构基础上进行新增,所以不继承直接将 IUnknown 中的方法搬过来也行。

由于 Rust 里面接口、类全部都以 struct 的形式表达,并且和 C++ 中的 struct 内存布局是有区别的,所以在定义接口虚表时,全部需要加上 #[repr(C)],代表该结构体内存布局和 C 完全一致。C 里面有 IUnknown,Rust 里也不需要我们从 IUnknown 开始实现,实际上在 windows-rs 和 winapi 这两个 crate 中都有实现,但是实现方式上有所不同。主要体现在对 “接口指针” 的定义上,下面是使用 C、winapi、windows-rs 各自如何声明一个接口指针变量:

声明方式
C IUnknown *p = NULL;
winapi let p: *mut IUnknown = ptr::null_mut();
windows-rs let p: IUnknown;

可以看出来 winapi 的接口定义方式更符合 c 的接口调用风格,而 windows-rs 从声明上则看不出来是一个指针,指针被隐藏在了内部:

#[repr(transparent)]
pub struct IUnknown(std::ptr::NonNull<std::ffi::c_void>);

transparent 可以理解为透传,相当于:pub type IUnknown = std::ptr::NonNull<std::ffi::c_void>,所以 let p: IUnknown 等价于 let p: std::ptr::NonNull<std::ffi::c_void>,这样才能看出来是个指针了。

对于这块暂时解释到这里,想更进一步理解具体怎么用 Rust 定义一个接口的话,可以借鉴我代码里对 IRundown 接口的实现方式。

接下来理解 COM 接口方法的调用过程,COM 实际上可以理解为 RPC 的一种上层实现,所以还是 RPC,调用接口的程序称为客户端,真正处理执行调用请求的称为服务端。之前列出的调用过程步骤中的第 3 步,使用 CoGetObjectCoCreateInstanceCoGetObjectContext 这些 API 获取接口指针,如果获取成功就相当于和服务端连接成功,当通过指针调用方法后,相当于发起一个请求到服务端了。

所以回到该技术中,该技术使用了一个名为 IRundown 的接口,此接口中包含一个可以执行回调的方法 DoCallback,定义如下:

pub DoCallback: unsafe extern "system" fn(this: *mut ::core::ffi::c_void, pParam: *mut XAptCallback) -> windows::core::HRESULT,

XAptCallback 参数设置回调地址和参数地址:

#[repr(C)]
#[derive(Clone, Copy)]
pub struct tagXAptCallback {
    pub pfnCallback: PTRMEM,                    // what to execute. e.g. LoadLibraryA, EtwpCreateEtwThread
    pub pParam: PTRMEM,                         // parameter to callback.
    pub pServerCtx: PTRMEM,                     // combase!g_pMTAEmptyCtx
    pub pUnk: PTRMEM,                           // Not required
    pub iid: windows::core::GUID,               // Not required
    pub iMethod: i32,                           // Not required
    pub guidProcessSecret: windows::core::GUID  // combase!CProcessSecret::s_guidOle32Secret
}
pub type XAptCallback = tagXAptCallback;

pfnCallback 为回调函数指针,pParam 为参数指针。加上之前说的 C/S 架构,接口调用请求实际上是在服务端处理的,所以当服务端进程接收到执行回调的请求后,触发回调执行完成代码注入。

大致的技术利用原理就这些,其他的都是一些细节问题,比如如何获取到该接口指针、如何注入到任意进程中去,这两个实际上是一个问题,前面说过成功获取接口指针即是连接到目标进程,所以对于此类问题的根本是 “哪些进程属于这个接口的服务进程”。

好像目前唯一好用的查看 COM 进程信息的工具就是 OleViewDotNet 了,需要提前使用 windbg 或者其他调试器把 combase.dll 的符号下载到本地,然后配置到 OleViewDotNet 里,否则是查不到任何结果的:

x

然后在 Processes -> All Proccess -> By Name 打开 COM 进程列表,搜索 IRundown:

x

相当于执行 com-inject.exe list -v

这些进程中存在 IRundown 接口指针,由于 IRundown 接口的实现者是 combase.dll,所以加载 combase.dll 的进程都有可能。

windbg 里面可以直接按下面的方式找 IRundown 接口虚表:

0:004> x /D /d combase!*CRemoteUnknown*
 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
00007fff`637008c8 combase!CRemoteUnknown::`vftable' = <function> *[13]
0:004> dx -r1 (*((combase!void (__cdecl*(*)[13])())0x7fff637008c8))
(*((combase!void (__cdecl*(*)[13])())0x7fff637008c8))                 [Type: void (__cdecl* [13])()]
    [0]              : 0x7fff6353e790 : combase!CRemoteUnknown::QueryInterface+0x0 [Type: void (__cdecl*)()]
    [1]              : 0x7fff635ae3b0 :  [Type: void (__cdecl*)()]
    [2]              : 0x7fff635ae3b0 :  [Type: void (__cdecl*)()]
    [3]              : 0x7fff63520600 : combase!CRemoteUnknown::RemQueryInterface+0x0 [Type: void (__cdecl*)()]
    [4]              : 0x7fff6351a390 : combase!CRemoteUnknown::RemAddRef+0x0 [Type: void (__cdecl*)()]
    [5]              : 0x7fff6352f2b0 : combase!CRemoteUnknown::RemRelease+0x0 [Type: void (__cdecl*)()]
    [6]              : 0x7fff6355ad50 : combase!CRemoteUnknown::RemQueryInterface2+0x0 [Type: void (__cdecl*)()]
    [7]              : 0x7fff6355afa0 : combase!CRemoteUnknown::AcknowledgeMarshalingSets+0x0 [Type: void (__cdecl*)()]
    [8]              : 0x7fff636765a0 : combase!CRemoteUnknown::RemChangeRef+0x0 [Type: void (__cdecl*)()]
    [9]              : 0x7fff6358ee90 : combase!CRemoteUnknown::DoCallback+0x0 [Type: void (__cdecl*)()]
    [10]             : 0x7fff6358ee80 : combase!CRemoteUnknown::DoNonreentrantCallback+0x0 [Type: void (__cdecl*)()]
    [11]             : 0x7fff634d29b0 : combase!CRemoteUnknown::GetInterfaceNameFromIPID+0x0 [Type: void (__cdecl*)()]
    [12]             : 0x7fff6355b140 : combase!CRemoteUnknown::RundownOid+0x0 [Type: void (__cdecl*)()]
0:004> u 7fff6358ee90
combase!CRemoteUnknown::DoCallback [onecore\com\combase\dcomrem\remoteu.cxx @ 1843]:
00007fff`6358ee90 48895c2408      mov     qword ptr [rsp+8],rbx
00007fff`6358ee95 57              push    rdi
00007fff`6358ee96 4883ec40        sub     rsp,40h
00007fff`6358ee9a 0f104234        movups  xmm0,xmmword ptr [rdx+34h]
00007fff`6358ee9e 488bda          mov     rbx,rdx
00007fff`6358eea1 488d542430      lea     rdx,[rsp+30h]
00007fff`6358eea6 f30f7f442430    movdqu  xmmword ptr [rsp+30h],xmm0
00007fff`6358eeac e83b000000      call    combase!CProcessSecret::VerifyMatchingSecret (00007fff`6358eeec)
0:004> bp 7fff6358ee90

其他细节或者挖掘思路直接看一下大佬的文章解惑吧 http://www.mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/。

已经解决的问题

原项目运行后可能会遇到一些问题,在重写时简单处理了一下,问题如下:

A、在获取目标进程 IPID 列表偏移时,判断条件不够导致后续步骤访问到错误地址导致崩溃

我在 find_ipid_table 中加了些条件,然后就没遇到过着个问题了:

if (*cpage)._pgalloc._cPages <= 0 || (*cpage)._pgalloc._cEntries <= 0 {
    continue;
}

B、原项目默认取第一个 IPID 进行交互,但是第一个 IPID 对应的 TID 可能是 0x00000xFFFF,导致回调失败

IPID 是一个 GUID,是对接口指针的标识,具有一定的格式:xxxxxxxx-yyyy-zzzz-xxxx-xxxxxxxxxxxxyyyy 的位置代表进程 PID,zzzz 的位置代表线程 TID,如果线程 ID 无效会导致获取的 server context 不正确,最后虽然这个接口指针的状态虽然不是 IPIDF_DISCONNECTED,但是最终调用 DoCallback 时依然返回错误:“被调用的对象已与其客户端断开连接。 (0x80010108)”。

所以我在获取接口指针时,加了些过滤,优先使用 TID 有效的 IPID:

let x: Vec<_> = entries.iter().filter(|x| x.ipid.tid > 0x0 && x.ipid.tid < 0xffff).collect();
let y: Vec<_> = entries.iter().filter(|x| x.ipid.tid == 0x0).collect();
if x.len() > 0 {
    (*rc).ipid = x[0].ipid;
    (*rc).oxid = x[0].oxid;
    (*rc).oid = x[0].oid;
} else if y.len() > 0 {
    (*rc).ipid = y[0].ipid;
    (*rc).oxid = y[0].oxid;
    (*rc).oid = y[0].oid;
} else {
    (*rc).ipid = entries[0].ipid;
    (*rc).oxid = entries[0].oxid;
    (*rc).oid = entries[0].oid;
}

未解决的问题

  1. 每次注入都会消耗掉目标进程中的一个接口指针,不确定为什么会自动释放掉,当用完之后就会一直注入失败了
  2. 对于 TID 为 0x00000xFFFF 时总是注入失败,怎么解决
  3. 通用于 x86x86_64 的 COM 进程
本文转载于网络 如有侵权请联系删除

相关文章

  • 陈春花与莫言,都有苦难言

    作者|曾响铃 文| 响铃说(xiangling0815)现代版的“秀才遇到兵,有理说不清”,正在这个七月上演。不久前,诺贝尔文学奖获得者莫言,在自己公号发布头条文章《莫言:这些作品真不是我写的》,用表情包在线打假。而在莫言发布打假文章之前,还有另一位学者也深陷其中,且更加凶猛,这就是被人“吹”上华为神坛的学者陈春花。有多猛呢?向来惜字如金的华为,这次也不得不发布声明——华为与陈春花无任何关系,华为不了解她,她也不可能了解华为。逼华为出手的源头,是“网络上有1万多篇不实信息——夸大、演绎陈春花教授对华为的解读、评论和反复炒作......”。同天,陈春花也发布了声明表示,这些文章不是我写的,且已聘请律师就此类侵权行为追究责任。一时之间,网络上各种舆论满天飞,秀才们似乎也不能完全说清到底有多少“冒名者”,无一例外都成了受害者。虽然不少旁观网友大呼莫言表情包在线打假“可爱”,但对莫言来讲,或许更多的感受可能是“可怕而不被爱”吧。而在笔者眼中,莫言和陈春花等学者被“冒名”,其实藏着不少“连环计”——无中生有、暗渡陈仓、浑水摸鱼等等,被用得炉火纯情,背后的目的,当然还是利益。 1 无中生有皆为利中

  • LeCun论文被指「洗稿」? LSTM之父发文怒怼:抄我的还标原创

    【新智元导读】LSTM之父、暴脾气大爷JürgenSchmidhuber又开炮了?这回怼的是LeCun,说最近的新论文是炒了自己20多年前的冷饭,只不过换了种说法而已。图灵奖得主YannLecun,作为AI界的三巨头之一,他发表的论文自然是被人当成「圣经」来学习的。然而,最近突然有一个人跳出来炮轰LeCun「炒冷饭」:「无非就是把我的核心观点换种说法罢了」。莫非……没错,此人正是「LSTM之父」JürgenSchmidhuber。Schmidhuber表示,LeCun的这篇论文并未提及1990-2015年期间的重要成果,文中所提及的「主要原创成果」,包括「学习子目标、可预测的抽象表征、多个时间尺度」等概念,他们也已经发表过了。原推中用的rehash这个词,也就是把原先的idea用另一种方式表达而不做创新,妥妥的「洗稿」了。 同时,他还发长文详细地列出了证据。当然,这只能算是Schmidhuber的一面之词罢了。不过,网友们显然并不买账。「你过去是AI界的一位重量级人物,但现在你出名的地方在声称每个人的学术成果都是剽窃了你的观点」。「神经网络、transformers、LSTMS是你发明

  • Yaf---加载规则插件使用

    Yaf在自启动的时候,会通过SPL注册一个自己的Autoloader,出于性能的考虑,对于框架相关的MVC类,YafAutoloader只以目录映射的方式尝试一次. 类型后缀映射路径控制器Controller默认模块下为{项目路径}/controllers/,否则为{项目路径}/modules/{模块名}/controllers/数据模型Model{项目路径}/models/插件Plugin{项目路径}/plugins/一个简单的自我理解<?php classIndexControllerextendsYaf_Controller_Abstract{ publicfunctionindexAction(){//默认Action $mod=newTserModel();//自动加载model下面的test.php文件 $mod->query();//调用TestModel里的query方法 $user=newUserPlugin();//自动加载plugins下面的user.php文件 $this->getView()->assign("titl

  • Lasso 稀疏约束 + Group Lasso 分组最小角回归算法

    背景Lasso(leastabsoluteshrinkageandselectionoperator,又译最小绝对值收敛和选择算子、套索算法)是一种同时进行特征选择和正则化(数学)的回归分析方法,旨在增强统计模型的预测准确性和可解释性,最初由斯坦福大学统计学教授RobertTibshirani于1996年基于LeoBreiman的非负参数推断(NonnegativeGarrote,NNG)提出。Lasso算法最初用于计算最小二乘法模型,这个简单的算法揭示了很多估计量的重要性质,如估计量与岭回归(Ridgeregression,也叫Tikhonovregularization)和最佳子集选择的关系,Lasso系数估计值(estimate)和软阈值(softthresholding)之间的联系。它也揭示了当协变量共线时,Lasso系数估计值不一定唯一(类似标准线性回归)。 范数(norm)定义首先需要了解一下几种向量范式的定义: 0-范数:即向量中非零元素的个数\|w\|_0=\sum_i1(w_i\neq0)1-范数:即向量元素绝对值之和,matlab中可以调用函数norm(x,1)\|

  • 收藏!!MYSQL常用命令

    常用功能命令1.导出整个数据库1mysqldump-u用户名-p–default-character-set=latin1数据库名>导出的文件名(数据库默认编码是latin1) 2 3mysqldump-uwcnc-psmgp_apps_wcnc>wcnc.sql复制2.导出一个表1mysqldump-u用户名-p数据库名表名>导出的文件名 2 3mysqldump-uwcnc-psmgp_apps_wcncusers>wcnc_users.sql复制3.导出一个数据库结构1mysqldump-uwcnc-p-d–add-drop-tablesmgp_apps_wcnc>d:wcnc_db.sql 2 3-d没有数据–add-drop-table在每个create语句之前增加一个droptable复制4.导入数据库1A:常用source命令 2 3进入mysql数据库控制台, 4 5如mysql-uroot-p 6 7mysql>use数据库 8 9然后使用source命令,后面参数为脚本文件(如这里用到的.sql) 10 11mysql>so

  • 漫画说算法|人工智能与我们的未来

    为了让小伙伴更加容易理解经典算法,留下深刻印象,小白决定创办「漫画说算法」,分享讲解算法的漫画文章,在阅读漫画的过程中学习。如果小伙伴有收藏的优秀文章,欢迎后台留言与小伙伴们一起分享。本文转载自公众号:大鱼AI作者:武博士、宋知达、袁雪瑶、聂文韬本节我们会以生动有趣的漫画来介绍关于人工智能(AI)相关的故事,你将会学习到:人工智能与人类的未来1.4人工智能与人类的未来1.4.1科技奇点什么,它会到来吗?有人预测,到了2045年,计算机将会超越人类大脑。这是基于计算机芯片性能每18个月提升一倍的假设,这个假设就是著名的摩尔定律。如果这个预言成真,那么在人类的不断努力下,不久的将来,可以制造出比人类还聪明的人工智能。这种人工智能诞生后,由于它比人类聪明,它可以制造比它聪明的人工智能。在这样的推演下,人类就会被远远抛在后面。由此可知,所谓的科技奇点(技术的的特异点),指的就是人工智能有办法制造出更加聪明的人工智能的时间点。原本从第一级到第四级的人工智能,都需要人类手动创造。但是当人工智能有办法制造出比自己聪明的人工智能时,便进入了一种截然不同的境界,即使新的人工智能比原来只聪明的一点点。我们

  • 剪枝需有的放矢,快手&罗切斯特大学提出基于能耗建模的模型压缩

    机器之心原创作者:思源神经网络压缩式需要明确目的的,它不能还是「为了压缩而压缩」。最近,快手Y-Tech西雅图AIlab联合罗切斯特大学等研究者提出了一种基于能耗建模的压缩方法,他们一脉相承的两篇论文分别被ICLR2019和CVPR2019接收。在这篇文章中,我们将介绍这种新型模型压缩的核心思想及主要做法,神经网络压缩也许该走向有目标的前进之路了。模型压缩的应用目前快手的手机端应用,基本上都会进行模型压缩,因为不管是能耗、效率,还是推断速度,都需要满足很多条件才能投入使用。不管是将深度学习模型部署到云端还是移动端,模型压缩都必不可少。快手Y-Tech西雅图AI团队的负责人刘霁教授表示部署到手机端的模型,例如美颜相机、视频的人脸识别、姿态识别等应用都会经过模型压缩,其重点在于减小模型体积、降低模型能耗,以及保证推断效率。部署到服务器也面临类似问题,因为每一秒都会有成千上万条调用请求,而这些请求需要在规定时间内得到响应。例如更新一次推荐视频,快手的服务器在接到请求以后需要立即计算,把最合适的Top-N视频反馈到客户端,这种响应甚至要控制在几毫秒才能满足用户良好的体验。正因为有很多实际需求,

  • Linux命令(43)——paste命令

    1.功能paste命令将多个文件的相应行默认以Tab分隔符横向连接起来,输出到标准输出。paste后可接多个文件,不限于2个文件。如果文件写成“-”,表示内容来自标准输入。paste相对于join来说,简单许多,不需要有相同的字段才能按行连接。2.格式pasete[选项][file1...]复制3.选项说明-d,--delimiters=[LIST]:用指定的域分隔隔符取代Tab。 -s,--serial:顺序地合并一个文件的所有行到一行。 --help:显示帮助信息。 --version:显示版本。复制4.示例有两个文件file1.txt和file2.txt,内容如下:#file1内容 [root@tencent~]#catfile1.txt abc def ghi #file2内容 [root@tencent~]#catfile2.txt 123 456 789 012复制(1)将文件file1.txt的所有行合并到一行。[root@tencent~]#paste-sfile1.txt abcdefghi #指定域分隔符为: [root@tencent~]#paste-sfil

  • 特斯拉股价暴跌,疯狂烧钱是否真的能够带来高额回报?

    “疯狂烧钱”并不能成为公司持续亏损的理由,反而可能成为公司升级转型的关键所在。上周三,特斯拉发布第四季度财报,其后特斯拉CEO马斯克在电话会议上表示,特斯拉亏损收窄,营收同比增长88%,但与此同时其首席财务长JasonWheeler已确认离职,将于今年4月离开公司。此外,马斯克还表示,今年将实现Model3的量产和上市,但Model3在上市之前会消耗大量的资金,公司或将再次面临现金短缺危机。消息一出,特斯拉股价暴跌,从260美元上方跌至约230美元,同比下跌约6%,创近8个月最大盘中跌幅,马斯克身价也因此身价缩水约5亿元美元,福布斯实时富豪榜排名降至87位。股价大起大落,特斯拉正在为其“不理智”买单其实,特斯拉股价动荡已经不是什么新鲜事了,只近三个月,特斯拉股价就先后经历了3次大的动荡,先是从230美元暴跌至150美元下方,随后狂升至260美元上方,现在又跌回了230美元水平,显然,“大起大落”才是特斯拉股价的“常态”。此次股价大跌,外界普遍分析认为是与其高层变动和资金的持续消耗有关,但从特斯拉近几年的发展来看,高层变动仅是股价动荡的导火索之一,“疯狂烧钱模式”才是罪魁祸首。数据统计,

  • 2017年二零八科学会议——人工智能在电力领域的研究应用方向和关键技术

    人工智能是当前最具颠覆性的技术之一,各国政府、研究机构和企业已积极行动,制定技术战略、密切跟踪最新技术发展。2017年7月,国务院印发《新一代人工智能发展规划》,将人工智能提升到国家战略层面。8月,国家电网公司启动人工智能相关工作,形成《国家电网公司人工智能专项规划》。为探讨人工智能技术在电力领域的应用前景和方向,寻找人工智能在电力领域的着力点和突破点,中国电科院于12月6日召开主题为“人工智能在电力领域的研究应用方向和关键技术”的二零八科学会议,中国科学院院士周孝信、中国电科院总工程师汤涌、副总经理(副院长)王继业、副总经理(副院长)高克利出席会议,来自国网公司、科研单位、高等院校的50余位专家参加。会议邀请9位知名专家就人工智能技术进展及其在电力系统中的应用实践和展望做专题报告。与会专家就人工智能在电力领域的研究应用方向和关键技术进行了热烈而深入的讨论,并初步达成共识。报告内容王继业副总经理(副院长)致欢迎词并作题为“人工智能在能源电力领域的探索”的专题报告,从能源电力转型的视角切入,提出人工智能是智慧能源的核心支撑技术,智慧能源与未来电网是以平衡为约束的多目标函数,其因子众泛,条

  • 腾讯云API网关简介

    欢迎使用API网关API3.0版本。全新的API接口文档更加规范和全面,统一的参数风格和公共错误码,统一的SDK/CLI版本与API文档严格一致,给您带来简单快捷的使用体验。支持全地域就近接入让您更快连接腾讯云产品。更多腾讯云API3.0使用介绍请查看:快速入门 API网关(APIGateway)是API托管服务,提供API的完整生命周期管理,包括创建、维护、发布、运行、下线等。您可使用APIGateway封装自身业务,将您的数据、业务逻辑或功能安全可靠的开放出来,用以实现自身系统集成、以及与合作伙伴的业务连接。 注意: 本章节API网关API接口均为最新API3.0接口,后续API网关相关新增功能都会在此章节更新。我们强烈推荐您使用最新API3.0接口。 现有旧版API接口功能依然保持,未来可能停止维护,如您仍需使用旧版接口可参考:API网关API(旧版)概览。

  • MySQL插入性能优化

    可以从如下几个方面优化MySQL的插入性能。MySQL之SQL优化实战记录 代码优化 values多个 即拼接成一个insertvaluessql,例如 INSERTINTOMyTable (Column1,Column2,Column3) VALUES ('John',123,'LloydsOffice'), ('Jane',124,'LloydsOffice'), ('Billy',125,'LondonOffice'), ('Miranda',126,'BristolOffice'); 复制 一个事务 开启一个事务,批量操作完了才提交事务,而不是,操作一次就提交一次,这样io太高,插入太慢。 插入字段尽量少,尽量用默认值 注意事项:max_allowed_packet默认是1M,如何insertvaluessql太大需要上调这个值 关闭unique_checks 优化效果不是很明显,下面截图选自《MySQL数据库开发、优化与管理维护第2版》书籍 bulk_insert_buffer_size 这个参数只能对MyISAM使用,innodb无效 配置优化 innodb_buff

  • 适配

    http://blog.csdn.net/think_ma/article/details/40652719http://www.cocoachina.com/ios/20141026/10045.htmliPhone4S,iPhone5/5s,iPhone6竖屏:(w:Compacth:Regular)横屏:(w:Compacth:Compact)iPhone6Plus竖屏:(w:Compacth:Regular)横屏:(w:Regularh:Compact)iPad竖屏:(w:Regularh:Regular)横屏:(w:Regularh:Regular)AppleWatch(猜测)竖屏:(w:Compacth:Compact)横屏:(w:Compacth:Compact)

  • LuoguP5540:【模板】最小乘积生成树(几何逼近)

    题意:给定N点,M边,每条边有两个属性(a,b),现在让你选N-1条边出来,然后使得∑a*∑b最小。N<200,M<1e4; 思路:我们把∑a看成x,∑b看成y,那么一个方案对应一个二维坐标(x,y)。假设我知道了其中两个方案[A,B],那么,如果另外一个方案C更优,则在二维平面上,C至少要满足在A和B的左边。然后[A,C],[C,B]继续下推。这个有点像凸包的逼近,所以复杂度和凸包上的点数有关,其理论点数是sqrt(lnN)的。所以总的复杂度趋近于NlogN*sqrt(lnN); #include<bits/stdc++.h> #definelllonglong #definepiipair<ll,ll> #defineffirst #definesssecond #definerep(i,a,b)for(inti=a;i<=b;i++) usingnamespacestd; constintmaxn=2000010; structin{ intu,v;lla,b,C; }s[maxn]; boolcmp(inp,inq){returnp.

  • echarts-环形图处理图列中的点击,使百分比的数据列不发生变化,默认追加其他选项

    将下列代码copy的echarts编辑器中 app.title='环形图'; var$legendData=['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']; var$legendSelected={'直接访问':false}; var$seriesData=[ {value:335,name:'直接访问'}, {value:310,name:'邮件营销'}, {value:234,name:'联盟广告'}, {value:135,name:'视频广告'}, {value:1548,name:'搜索引擎'} ]; varoption={ tooltip:{ trigger:'item', formatter:"{a}<br/>{b}:{c}({d}%)" }, legend:{ orient:'vertical', x:'left', data:$legendData, selected:$legendSelected }, series:[ { name:'访问来源', type:'pie', radius:['50%','70%'], a

  • Bitcoin-NG

    Bitcoin-NG,一个新的可扩展的区块链协议   Bitcoin-NG仅受限于网络的传输延时,它的带宽仅受限于个人节点的处理能力。通过将比特币的区块链操作分解为两部分来实现这个性能改善:首领选择(leaderelection)和交易序列化(transactionserialization)。   Bitcoin-NG是一个序列化交易的区块链协议,该协议将时间划分为片段,每个片段中,都有一个单独的首领来负责序列化状态机器转换,由首领生成区块。协议介绍了两种类型的区块:用于首领选择的关键区块和包含账本记录的微区块。   关键区块用于选择首领,区块中包含了和比特币区块一样的信息,不同的是,它还包含了一个在随后的微区块中要用到的公钥。 图1:Bitcoin-NG链的结构。微区块(圆圈)是用私钥  来签名的,该私钥和最后关键区块(正方形)的公钥相          匹配。40%的交易费分发给首领,60%分发给下一个区块。    图2:当微区块很频繁时,几乎在每个首领更换时都会出现短暂的分叉

  • SQL数据库字段数据类型详细说明

    这里先总结数据类型。MySQL中的数据类型大的方面来分,可以分为:日期和时间、数值,以及字符串。下面就分开来进行总结。 日期和时间数据类型 MySQL数据类型 含义 date 3字节,日期,格式:2014-09-18 time 3字节,时间,格式:08:42:30 datetime 8字节,日期时间,格式:2014-09-1808:42:30 timestamp 4字节,自动存储记录修改的时间 year 1字节,年份 数值数据类型 整型 MySQL数据类型 含义(有符号) tinyint 1字节,范围(-128~127) smallint 2字节,范围(-32768~32767) mediumint 3字节,范围(-8388608~8388607) int 4字节,范围(-2147483648~2147483647) bigint 8字节,范围(+-9.22*10的18次方) 上面定义的都是有符号的,当然了,也可以加上unsigned关键字,定义成无符号的类型,那么对应的取值范围就要翻翻了,比如: tinyintunsig

  • ajax请求跨域问题

    ajax跨域,这个是面试的时候常被问到,也是在做项目的时候会遇到的问题,在之前的项目中就有遇到过,这里根据经验写了三种分享下 1.使用中间层过渡的方式       简单来说就是"后台代理",把跨域请求交给后台去执行,然后在前端用ajax访问后台获取数据便可,这种比较简单,就不多说了。 2.使用script标签     对于script来讲,没有所谓的跨域限制,所以一般可以用来实现跨域请求,请求方式(这里用jquery,也可以直接用<script>标签) $(function(){ $.getScript("http://localhost:14412/ajaxTest.aspx",function(){ alert(responseVal); }) })复制 后台对应代码 publicpartialclassajaxTest:System.Web.UI.Page { protectedvoidPage_Load(objectsender,EventArgse) { Re

  • 天满

  • 解决print spooler打印服务自动多次重启

    引用:解决printspooler打印服务自动停止的过程记录 办公室一台电脑的共享打印机突然无法打印,提示打印服务已停止,打开服务发现printspooler服务已经停止,同时打印机列表中打印机记录也全部消失。右键启动服务,打印机列表出现,但是刷新后发现printspooler服务又已经停止。 根据网上的解决方法,有人认为是打印服务的注册表被第三方软件干扰,更改了注册表的键值,导致打印服务被停止。解决方法如下: 开始->运行,输入regedit打开注册表编辑器 找到以下键值: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Spooler 选定Spooler这个文件夹,在右边窗口里找DependOnService这个键值 双击打开,里面多了个HTTP,把数据改为RPCSS,确定后退出注册表编辑器,重启计算机。 按照此方法解决后,发现printspooler服务依然会自动停止,对比打印服务正常电脑的注册表发现键值为PRCSSHTTP。所以说明这个键值被修改不是导致printspooler服务自动停止的原因。 网上还有其他解决

  • React Native 之 Flex

    组件的高度,宽度决定了在屏幕上的尺寸。React-Native中尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。 importReact,{Component}from'react'; import{AppRegistry,View}from'react-native'; classTestSizeextendsComponent{ render(){ return( <View> <Viewstyle={{width:50,height:50,backgroundColor:'powderblue'}}/> <Viewstyle={{width:100,height:100,backgroundColor:'skyblue'}}/> <Viewstyle={{width:150,height:150,backgroundColor:'steelblue'}}/> </View> ); } }; //注册应用(registerComponent)后才能正确渲染 //注意:只把应用作为一个整体注册一次,而不是每个组件

相关推荐

推荐阅读