| 关键词: nbsp 8195 一个 程序 SNMP CLibrary Engine 字段 挑战赛 加密 |
这一关是位于PWNABLE目录下的“Twentyfiveseventy”,通常来说这个目录下的关卡应该是通过一个漏洞利用来获取通关flag。下载这个文件[文件可在文后下载]之后,使用IDA-Pro打开,然后分析这个程序是做什么的,以及可能存在的一些BUG。通过逆向工程,我渐渐意识到这个程序中似乎用到了SNMP协议,最后看到挑战名指向RFC 2570才最终确认为SNMP V3版本。 通过对程序进行反汇编分析,了解到实际上程序在启动时就将挑战赛的flag加载进了内存之中。这使我更加确信常用的手法已经无法解决这个问题了。 进一步分析显示,只要通过正确验证以及加密的SNMP V3 GET包收到正确的OID请求,那么程序就会返回flag的值。 这一挑战看起来似乎需要进行大量的编程,即便是我已经拥有了执行库。再次检测之前的反汇编,分析看是否有明显的BUG跳出。从我所观察到的情况来看,程序实现SNMPV3采用MD5作为散列值,DES_CBC进行加密。 下图显示了SNMPV3的整体结构 挑战赛中的该二进制程序实际上有一个很严格的解析器,检测字段长度,值等。这些检测通常发送SNMP报告并填充一个新的SNMP GET内容就能够通过。SNMP报告是一个大多数字段值都为空的包。接着SNMP服务端将发回一个SNMP响应包。这其中的字段有Engine Id, Engine Time,和Engine Boots. 为了通过解析器,协议中仍然有些字段需要我们仔细确定。在程序数据部分中我发现了username, engine id,以及目标OID。他们分别为 “lbs”, “0x80007a6903deadbeefcafe”, “1.3.6.1.2.1.1.5.0.0.0” 。剩下的key字段需要构造一个合适的包,审查的设置加密key的函数,key实际上是随机产生的。engine time设置seed并返回客户端,作为一个增加的测试完整性,engine boots的值是由第一个随机生成的数字获得,可以用来验证随机数生成算法是否正确。 将engine time本地化,应该能够生成相同的随机加密key。由于我的库是在Java中执行,我需要执行一些JNA代码来使用本机的libc随机函数确保算法一致 inte**ce CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary(“libc”, CLibrary.class); void srand(int an_int); int rand(); } public static byte[] get_auth_key( long passedSeed, long engineBoots ){ byte[] retKey = new byte[32]; //Seed it CLibrary.INSTANCE.srand((int)passedSeed); //Throw away one long tempNum = CLibrary.INSTANCE.rand(); long bootTest = (( tempNum >> 32 ) >> 25) + (( tempNum) & 0x7F ) - (( tempNum >> 32 ) >> 25); if(engineBoots == bootTest){ //Create the encryption key for( int i = 0; i < 32; i++){ long retVal = CLibrary.INSTANCE.rand(); retKey[i] = (byte) ((retVal % 94) + 32); } } return retKey; } 接下来我们就要寻找突破身份验证的方法,我的一位队友发现了突破困境的方法。解析器仅仅是拷贝并验证md5的字节数,它的长度值在包中是指定。另外允许用户设置长度,这意味着有1/256的机会,与第一个字节匹配。 最后将所有信息综合,我打开Java SNMP客户端,经过十几次尝试最终获得flag。q@)$asllqkw4h5】 下载链接 链接:http://pan.baidu.com/s/1dD0aXA5 密码:rvvn |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|