西邮Linux兴趣小组2014级免试挑战题 (续)
在上一篇的博客中已经解到第四关了,现在继续挑战~~
【 第四关】
在上一关解压成功后,生成了一个file文件。用vim的二进制格式打开,转成十六进制,发现文件头格式如下:
是个以ELF字符开头的文件,那就是个可执行的文件(ps:关于这点同样可以用file命令或者binwalk工具分析,下面是file命令分析的截图,可以发现还是x64平台下的)。
给这个file文件加上执行权限:“chmod +x ./file”,执行一下,发现生成了一个data文件,同样用vim二进制打开转十六进制,发现如下字符串:
我嘞个X,java都来了@_@,再用file命令分析一下,发现是一个java class文件,版本是52.0的。google搜索了一下,说是javac将 .java 源文件编译为 .clsss 文件,最后由java 来运行 这个.class的目标文件。注意到上图第一、二行中包含了“SourceFile、tip.java”这些字符串。说明它的源文件是tip.java,所以需要将这个data目标文件再重命名为tip.class文件(ps:java中的共有类,其文件名必须和类名一致,不然就找不着类名了)。现在就可以直接执行这个.class文件咯,执行发现出错-_-
提示信息说“Exception in thread "main" java.lang.UnsupportedClassVersionError: tip : Unsupported major.minor version 52.0”,搜索了下,说是java的版本不支持,也就是说我这机子上的java版本太低了,用“java -version”看了下,本机是1.6的版本,搜一下java最新版本,已经到1.8了~_~,找其他同学的1.8版本的java跑一下试试,发现可以运行:
生成了一堆的字符串,一看还是比较熟悉的,是unicode编码,懒得写脚本,直接在线解码吧~
关于上面的tip.class文件,0xcch大牛说,可以使用jd-gui(java反汇编工具)打开。直接看到这个class文件的源码,复制出来再重新编译一下就行了:
根据提示“请把源程序的strcmp()返回值+1处理”,试着再执行以下这个file源程序。居然发现没有权限,咋回事?刚才不是加的执行权限么,ls查看了下,发现现在这个file文件确实没有执行权限。加上执行权限,执行发现报错:
好像是缺少一个共享的动态链接库,用ldd命令看看:
果然是缺少libstrlen.so这的动态链接库,google狂搜了一堆,发现很多类似的动态链接库都是自己实现的。莫非,还需要自己来写一个???先查看一下这个动态链接库都调用了那些函数吧,使用readelf查看这个file程序的文件符号表区中的条目,发现条目太多,考虑到链接库函数都是通过“UND”关键词定义的,所以使用条件过滤:
除了调用GLIBC的链接库之外,好像并没有调用其他的链接库哎。但是既然程序需要这个库,就随便生成这个库吧,用vim随便写个C代码:int foo(const char* s) {return 1;
} 使用gcc编译连接生成libstrlen.so动态链接库:
添加指定的所需动态链接库路径,使用ldd查看一下发现这个libstrlen.so已添加成功:
运行程序,居然可以运行成功哎^_^
其中的 tip:data 让想起了之前那个data的java文件的提示,看来需要反编译一下这个file程序了,使用objdump查看反编译后的代码:
发现这个程序中自定义了两个函数:outputdata函数和output函数。
首先开始从main()函数开始分析:它调用了自定义的outputdata函数,但是貌似并没有调用那个output函数。果断地使用gdb调试看看:
发现真没有调用那个output()函数,使用gdb打印这个output()函数,发现通关链接:
【 第五关】
打开链接(http://xiyoulinux.idina.cn)如下图,有两张图片,第一张是个很复杂的有向图,第二张看样子是权值表了,下面还有一个链接,点了下,下载了个文件,打开看是一大串的01字符串~~,习惯性的查看了下网页源码,发现这个“<!-- 解出此关后请带着密钥调戏微信小妞哦~~~~~~~~ -->”,看来已经到最后一关了,心好累 (~_~)。
先从那个01字符串入手吧,复制了开头一小部分,在线编码(https://paulschou.com/tools/xlate/)试试,发现在文本编码处,有英文字符串,用百度翻译了下,有明显的“肖申克的救赎......”。
应该是将01的二进制数转换成ASCII值,将二进制数8位一截,转换一下,python脚本:
#!/usr/bin/env python # coding=utf-8 f = open('a8a0dd247b3ed742').read() f = f.replace('\n','') list = [] text = [] count = 0 for i in f: count += 1 list.append(i) if count%8 == 0: bin = ''.join(list) list = [] ch = chr(int(bin,2)) text.append(ch) txt = ''.join(text) f2 = open('article.txt','w') f2.write(txt) f2.close()
vim打开这篇文章,找找看有啥东西咯,在文章的末尾发现了提示字符串:
翻译了下,应该是找最长的重复句子。呵呵,这用python不是分分钟的事么?根据上图的分析,分割句子直接使用字符串内建函数string.split('. '),需要注意的是分割符是“. ”(即:点加空格,而不是点)。python代码:
#!/usr/bin/env python # coding=utf-8 text = open('article.txt').read() sen = text.split('. ') dict = {} max = 0 for i in sen: if sen.count(i) > 1 and len(i) > max: max = len(i) count = 0 for i in sen: if len(i) == max: print 'len = %d\n%s' % (len(i),i) break count += 1
一共13行代码就搞定了^_^ 所以说,人生苦短,快用python!!下面是找出来的最长的重复句子:
“I wish I was young again”, 是啊,大学,更需要一颗永葆青春的心!!因为从这里,你开始走向成熟。。。
继续分析吧~~貌似这句话也没啥提示,可能之后会用到的,再分析那个有向图吧。分析一下那个权值表,数值在几十到几百之间,根据上面得出的句子,容易猜想到应该是ASCII值,根据ASCII表将可显示的字符值标到有向图上。
从v1开始,试着根据已存在权值的路径走一下这张图。从v1开始只能走v11,v11可以走到v12和v18,但是v12到v13没有给权值,估计是无法走通,所以从v11走到v18试试,根据上面的分析思路,v18也只能走v26,v26只能走v35,v35可以走的路线有v44,v20。但v44没有前路,只能走v20,v20只能走v28,如果v28向v21方向走下去,基本是不会了,应为走到这应该发现,那个s[ ]数组很重要(其实这一开始就应该想到,那个s[ ]数组应该很重要!)。
根据上面分析的思路,走完的路径是:v1->v11->v18->v26->v35->v20->v28->v37->v22->v30->v45->v51->v63->v55->v47->v64。将所走路径的权值字符串连起来就是:s[9]、L、s[1]、V、E、x、I、s[0]、O、s[2]、L、I、s[3]、u、X。哈哈,这会儿应该可以想到是啥了吧: i love xiyou linux! 还有5个大小写未知的字符,穷举也就2^5=32个,当然一个个试的话肯定能成功的,但是貌似之前找出来的那个最长的重复句子还没用上。根据s[ ]数组中的字母(i、o、y、u、n)和对应下标在上面的句子中匹配,很容易发现是在“young again”字符串中。所以最终的结果就是:iLoVExIyOuLInuX。发送到微信公众平台,返回通关成功!!!