1. 前言
本文将分析CVE-2017-13772,并总结mips栈溢出利用的一般思路。
阅读之前需要先了解mips汇编相关知识。
2. CVE-2017-13772漏洞成因
CVE-2017-13772是tp-link的栈溢出漏洞,如果ping功能处输入过长的ip地址会触发漏洞。一般而言,ping功能处我们一般是尝试命令注入,tp-link厂商在字符串过滤方面做得不错,一些特殊字符输入无效,所以这里只能挖掘溢出型漏洞。
IDA搜索定位字符串:
loc_453CE8:
la $t9, httpGetEnv
addiu $a1, (aPingAddr - 0x570000) # "ping_addr"
jalr $t9 ; httpGetEnv #http服务器通过httpGetEnv(ping_addr)获取ping_addr字段的值
move $a0, $s5
lw $gp, 0x70+var_58($sp)
la $a1, aDotype # "doType"
la $t9, httpGetEnv
move $a0, $s5
jalr $t9 ; httpGetEnv
move $s6, $v0 #httpGetEnv(ping_addr)返回值在v0,在上面一句执行之前,会保存在s6
lw $gp, 0x70+var_58($sp)
la $a1, aIsnew # "isNew"
la $t9, httpGetEnv
move $a0, $s5
jalr $t9 ; httpGetEnv
move $s3, $v0
lw $gp, 0x70+var_58($sp)
beqz $s6, loc_454640
move $s0, $v0
接着跟踪s6寄存器,单击一直往下看,直到这里才发现对s6的调用 ipAddrDispose($s6)
la $t9, httpGetEnv
la $a1, aTrhops # "trHops"
jalr $t9 ; httpGetEnv
move $a0, $s5
lw $gp, 0x70+var_58($sp)
nop
la $t9, atoi
nop
jalr $t9 ; atoi
move $a0, $v0
lw $gp, 0x70+var_58($sp)
move $a0, $s6
la $t9, ipAddrDispose #ipAddrDispose($s6)
nop
jalr $t9 ; ipAddrDispose
move $s1, $v0
lw $gp, 0x70+var_58($sp)
beqz $v0, loc_454280
move $v1, $v0
跟进ipAddrDispose
接下来分析ipAddrDispose
ipAddrDispose 中发生栈溢出的部分反汇编大致如下:
void ipAddrDispose(char * pingaddr):{
char pingaddr_tmp[0x33] = {
0};
int len = strlen(pingaddr);
memset(pingaddr_tmp,0, 0x33);
int i=0,j=0;
for(; i {
if(pingaddr[i]!=' ')
{
pingaddr_tmp[j]=pingaddr[i] // 是这里发生栈溢出
j++;
}
}
strcpy(pingaddr, pingaddr_tmp);//这里只是拷贝回去除空格的字符串到pingaddr
.........
}
从函数一开始分析可得栈的结构如下:
由栈的结构可知我们最后能够控制 s0 s1 ra,并且可以知道覆盖的偏移,pingaddr='A'(0xAC-0xC)+ s0+s1+ra,
pingaddr='A'0xA0+ s0+s1+ra,。
3. CVE-2017-13772漏洞利用
3.1 mips漏洞利用流程
mips漏洞利用首先需要sleep(nS)更新codecache,然后才能正确执行栈上的代码。
如果想运行反向shell,大致可以思考出这样的流程:
设置a0=1,跳转到sleep函数
获取栈的地址,跳转到栈上执行代码。
3.2 mips跳转
在mips中,跳转的方式有:
① 设置寄存器t9,跳转到寄存器t9。如:
move