Tomcat Filecoin C语言 压制组装机 自动化部署 arrays ajax lua 河南普通话考试 jq去除空格 lora开发 matlab不等于 oracle行转列函数 SketchUp 安装python mysql学习 python环境安装教程 java新特性 linux系统教程 php网络编程 flash实例教程 rewritebase redis入门指南 图解设计模式 html特殊字符 7个人 teraterm 疯狂java讲义 脚本列表 小度音箱app 速查表 数据库建模工具 lol世界第一 内存条是什么 文字转音频软件 c4d序列号 class选择器 迅雷共享会员 pygame安装教程 凯立德地图下载
当前位置: 首页 > 学习教程  > 编程语言

记moectf2020新生赛 及 部分MISC题WP

2020/10/8 19:10:44 文章标签:

大二老腊肉第一次参加新生赛,虽然被hidden了,但还是玩的挺开心🙃 由于是新生赛,题目普遍难度不大,挑了几道比较有趣的题目写了WP WP目录MISC-两只企鹅MISC-Show offCRYPTO-Easy RSA (非预期MISC-两只企鹅 …

大二老腊肉第一次参加新生赛,虽然被hidden了,但还是玩的挺开心🙃

由于是新生赛,题目普遍难度不大,挑了几道比较有趣的题目写了WP

WP目录

    • MISC-两只企鹅
    • MISC-Show off
    • CRYPTO-Easy RSA (非预期

MISC-两只企鹅

下载题目得到一张🐧图片,打开winhex拖到尾部发现压缩包。
用winhex搜索“PK”找到压缩包头部,正好也找到了压缩包密码。
在这里插入图片描述
分离压缩包并解压,得到flag.pyc,第一时间想到用uncompyle6到pyc反编译

uncompyle6 -o flag.py flag.pyc

然后运行flag.py画了另一只企鹅 (单身🐕HP-1

在这里插入图片描述

flag.py最后有DES加密过的flag,只有找到密钥才能解密。
密钥找了半天啥也找不到,就开了hint…说要注意冗余代码的作用,又卡了好久
直到群里师傅说到 Stegosaurus…

Stegosaurus是一种用于在Python字节码中嵌入Payload的隐写工具
具体可以看 https://www.freebuf.com/sectool/129357.html

直接用 Stegosaurus 解出pyc文件中隐藏的DES密码在这里插入图片描述
运行flag.py输入密码得flag
在这里插入图片描述

MISC-Show off

(又是一道吃🐕粮的题

题目给了一个图片和一个加密脚本。通过阅读脚本,发现脚本把另外一张jpg的数据通过或和与非运算隐藏在了所给图片的RGB值中,其中每个色块隐藏了3位二进制值

#关键代码
if ((data[curr//8] >> (curr%8)) & 1) == 1:#隐藏位为1
	pixel[k] &= ~(1 << (table.index(key[curr%KeyLen])%8) )
else:#隐藏位为0
	pixel[k] |= (1 << (table.index(key[curr%KeyLen])%8) )

我们现有的是运算之后的色块RGB值和key的值。由于我太菜,不知道怎么倒回去求 发生了或运算还是与非运算,那就爆破吧!2333

def solve(c,key):#爆破
    for i in range(256):
        if i &~ key==c:
            return '1'
    return '0'

这样我们就得到了隐写进去的jpg文件的所有的01序列,也就得到了这张jpg图片
解密脚本:

#!/usr/bin/python3

from PIL import Image, ImageDraw

table = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?!."
Key = "Wouldyouliketoseemygirlfriend?"


def solve(c,key):
    for i in range(256):
        if i &~ key==c:
            return '1'
    return '0'


class Cover:
    def __init__(self,raw_path):
        self.img = Image.open(raw_path)
        self.img_heigh, self.img_width = self.img.size
        self.draw = ImageDraw.Draw(self.img)

    def extract(self,key:str):
        s=self.img_heigh*(self.img_width)
        KeyLen = len(key)
        res=[]
        temp=''
        curr=0
        for i in range(self.img_heigh):
            for j in range(self.img_width):
                pixel = list(self.img.getpixel((i,j)))
                for k in range(3):
                    #print(pixel[k],(1 << (table.index(key[curr%KeyLen])%8)) )
                    temp+=solve(pixel[k],(1 << (table.index(key[curr%KeyLen])%8)))
                    curr+=1
                    if curr%100000==0:#输出解密进度
                        print(curr,curr/s/3)
                    if len(temp)==8:#每8位二进制转换为16进制
                        t=list(temp)
                        t.reverse()	#这样解的二进制序列是反着的,需要倒回来
                        res.append(int(''.join(t),2))
                        temp=''

        f=open('solve.jpg','wb')
        f.write(bytes(res))
        
        return bytes(res)
        

def show_off():
    '''
    with open("./test.txt", "rb") as f:
        data = f.read()
    '''
    new_cover = Cover("merged.png")
    new_cover.extract(Key)

if __name__ == "__main__":
    show_off()

打开图片,啊这?!(单身🐕HP-100
在这里插入图片描述
右击图片查看属性,在备注栏找到flag
(🐧,yyds!
在这里插入图片描述

CRYPTO-Easy RSA (非预期

这题不小心用MISC的方法把⏳带佬的RSA给非预期了…
下面说一下思路:

题目给了加密后的PNG数据和加密脚本。阅读脚本,发现是用随机生成的key逐位异或PNG文件数据,最后用RSA加密了key。

由题目中key的生成看出key共有38位,key的数据 0-255

key = b''.join([urandom(1) for _ in range(38)])

为了形象地表达,我们画一个表格
在这里插入图片描述
我们知道PNG文件是有固定格式的(具体可以百度

①先看PNG文件头。随便找一张PNG,用winhex打开。我标蓝了文件头的前38比特,其中划红线的比特大多数的PNG都是一样的。
在这里插入图片描述
那么通过异或密文和明文,可以还原key的相应位。
在这里插入图片描述
②然后看文件尾,PNG文件尾12比特固定为 00 00 00 00 49 45 4E 44 AE 42 60 82
在这里插入图片描述
那么文件尾对应key中的哪几位呢?

我们用全文长度对38(key的长度)取余,发现结果是36。key又是循环使用的,说明文件尾12比特对应了key的24-35位。
在这里插入图片描述
③CRC32爆破PNG宽高求key中间部分

CRC32爆破PNG宽高是MISC中的常用手段,下图划红线的部分就是划蓝线部分的CRC32值
在这里插入图片描述
既然我们已知key的相应位,我们可以通过异或轻易求出flag.png的CRC32,通过对flag.png高宽的爆破,得到明文的16-23比特,再异或得到key的16-23比特。

下面给出一个python的爆破脚本

import zlib
import struct
crc32key = 0xCE084A0A #补上0x,winhex下copy hex value。
data = bytearray(b'\x49\x48\x44\x52\x00\x00\x05\x4A\x00\x00\x07\x02\x08\x06\x00\x00\x00')   #winhex下copy grep hex。
n = 4095 #理论上0xffffffff,但考虑到屏幕实际/cpu,0x0fff就差不多了
for w in range(n):#高和宽一起爆破
    width = bytearray(struct.pack('>i', w))#q为8字节,i为4字节,h为2字节
    for h in range(n):
        height = bytearray(struct.pack('>i', h))
        for x in range(4):
            data[x+4] = width[x]
            data[x+8] = height[x]
        crc32result = zlib.crc32(data)
        if crc32result == crc32key:
            print(width,height)
            print(int.from_bytes(width,"big"),int.from_bytes(height,"big"))
            print(hex(int.from_bytes(width,"big")),hex(int.from_bytes(height,"big")))

        

得到0x104,0x104,则flag.png对应位为: 00 00 01 04 00 00 01 04
在这里插入图片描述
④最后两比特通过爆破RSA解出
只需遍历最后两比特,用RSA加密key,与题中给出的cipher比较即可。
(遍历次数只有256*256次,完全可以爆破。)
在这里插入图片描述
通过以上四步我们就还原了key可以开心地解密了(因为是异或加密,解密就用加密脚本再加密一次就行了)

下面给出解密脚本

from random import *
from gmpy2 import *
from Crypto.Util.number import *
from os import urandom
import zlib
import struct
XOR = lambda s1,s2 : bytes([x1^x2 for x1,x2 in zip(s1,s2)])

def enc(plain , key):
    block = len(plain) // len(key)
    res = b''
    if len(plain) % len(key) != 0:
        block += 1
    for i in range(block):
        res += XOR(plain[i*len(key):(i+1) *len(key)] , key)
    return res

def brute_force(key):
    cipher = 6295099350956528607396037601959877791934298828699677426193295804984422774839568282303538751735922668555038227591570508075836074695625068231718282637434619892411169336112708789051866841386960010983915517645375007603334301928436122113314644281698850356618954553636354588295318626415800893401794520007438195584651069726083411367546831544328390372733644828779287264837918630675648320615405654401121853964018368418748858627359640564171296914178768702389891031507220222973953333450633882912483139393113713737597059909038607300118809911390415352026833692334281800776950518743683416169290877451319659303510788506268753501781
    n = 18960722153219768424825297430288596402599615217676565923231065891419305439903969133336842165182164434305093888822528498525074593142143485234947709395152694407269932336781777523140964102701768500976985551580573991501756530871678077669095976326733950375907332862285201282966826531285878400261799511805034490220073023034504007192915282979526255340588329327377354539737224907994999568858311693959486822039283333461158422904468721851447600849924776566655800183080470425226397793377929935260296448192941725176241434514639433822949600965755910239847434831269722996200119639816772695986801602222805123304519611949635935587881
    e = 7
    for i in range(256):
        for j in range(256):
            key[36]=i
            key[37]=j
            k=bytes_to_long(bytes(key))
            if pow(k,e,n)==cipher:
                return

f=open('enc_flag.png','rb')
c=f.read()
f.close()
f=open('sample.png','rb')#sample:一张正常的PNG
s=f.read()
f.close()

s_start=s[:16]
s_end=s[-12:]
c_start=c[:16]
c_end=c[-12:]


k_start=XOR(s_start,c_start)#key 0-15
k_end=XOR(s_end,c_end)  #key 24-35


#爆破出来是0x104*0x104,异或解出key 16-23
k_middle=[107, 56, 164, 91, 186, 40, 226, 217]#key 16-23
#ps 因为我懒得加 CRC32 加密脚本了,直接把爆破好的key放过来了.....

key=[]
for i in list(k_start):
    key.append(i)
for i in list(k_middle):
    key.append(i)
for i in list(k_end):
    key.append(i)
key.append(0)
key.append(0)
            
brute_force(key)

#print(key)

f = open('flag.png' , 'wb')
m = enc(c , key)
f.write(m)
f.close()

解密后扫码得flag

若有错误,欢迎指出~
END~


本文链接: http://www.dtmao.cc/news_show_250106.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?