Description
Congratulations on discovering Admin’s store! Admin is currently developing a powerful AI recommender system. Go around and find out Admin’s secret score for various goods!
This challenge only provides an nc connection.
Solution
您可以通过下列交互获得一系列提示:
-
input a name more than 50 ascii–>
Sorry, you are not me or your name is too long but I can call you Bob _
I guess you are cute, so here is a tip: Do not eat too much 1da!!! -
input a non-numeric(such as ‘A’) when buy goods–>
What? Sorry, you can not buy anything today. This may affect your membership(A month of continuous shopping)
-
buy 10 1da–>
You eat too much 1da and You triggered the hidden task: Get membership!
-
buy another 20 banana priced 1–>
Dear Membership Bob
I will show you my Recommendation system. It contains A super AI and I test it myself!
But before I show that, what about a easy game?
Your answer is(Y/N):
您将得到一个用户商品评级矩阵,并被要求为第一行部分修复这些零。最后的答案是由第一行数字组成的字符串的md5值。
Great! You like it!
Here is the game, please find my score(integer) to those goods which have 0 score:
beginmatrix
[[40, 0, 0, 41, 42, 0, 30, 43, 0, 34, 32, 0, 32, 0], [31, 26, 38, 32, 27, 12, 21, 34, 22, 28, 23, 33, 23, 19], [21, 26, 28, 22, 31, 22, 19, 22, 30, 16, 21, 13, 21, 29], [19, 24, 27, 23, 26, 13, 15, 22, 24, 18, 23, 22, 23, 21], [37, 44, 51, 43, 48, 25, 29, 42, 44, 34, 41, 40, 41, 39], [29, 40, 42, 35, 45, 26, 25, 33, 43, 26, 37, 29, 37, 39], [24, 28, 32, 26, 32, 20, 20, 26, 30, 20, 24, 20, 24, 28], [32, 30, 41, 35, 31, 13, 22, 36, 26, 30, 28, 37, 28, 22]]
endmatirx
where row stand for user and col stand for goods
The good and user embedding dim are both 3!
The flag is md5(first row)
Example: if the first row is [14 13 9 22 20 25 14 27 20 15 19 10 32 21] md5(141392220251427201519103221)==59d25d2c3cc2bb1d27f550329d35f5a5
So, the answer is 59d25d2c3cc2bb1d27f550329d35f5a5
Now, what is your answer?
您可以使用矩阵分解算法轻松解决这一挑战。矩阵分解算法是推荐系统中一种经典的算法。由于用户和商品的embedding维度已被提示为3,因此可以直接使用矩阵分解算法来获得最终结果,而无需对维度大小进行暴力搜索。
服务器脚本
import numpy as np
import random
import hashlib
from func_timeout import func_set_timeout
@func_set_timeout(10)
def getinput():
tmps=input()
return tmps
def Main():
s = 'Welcome to **Admin**\'s shop, I will recommend what may you like!'
print(s)
print('May I know your name(**less than 50 ascii**), please?')
name = getinput()
if ('Admin' in name or len(name) > 50):
name = 'Bob'
print('Sorry, you are not Admin or your name is too long but I can call you Bob ^_^')
print('I guess you are cute, so here is a tip: Do not eat too much 1da!!!')
else:
print("Welcome, " + name + '. Thank you for your support, enjoy your shopping!')
menu = """
These are what you can buy.
no.0 1da price: 10
no.1 apple price: 2
no.2 f1ag price: 1999
no.3 banana price: 1
no.4 xctf price: 5
no.5 b3rpsu1t price: 3
no.6 0l0_3ider price: 108
"""
goodlist = [('no.0 1da', 10), ('no.1 apple', 2), ('no.2 f1ag', 1999), ('no.3 banana', 1), ('no.4 xctf', 5)
, ('no.5 b3rpsu1t', 3), ('no.6 0l0_3ider', 108)]
money = 120
cnt = 0
day = 0
while (True):
print('day:', day)
flag = False
for i in goodlist:
if (money >= i[1]):
flag = True
break
if (flag == False):
print('?????????,you do not have enough money!')
break
print('What would you like to buy?', name)
print(menu)
print('How about some', goodlist[np.random.randint(0, len(goodlist))], '?')
print('Please input your good number:')
tmpnum = getinput()
goodid = -1
for i in tmpnum:
if (i.isdigit()):
goodid = int(i)
break
if (goodid == -1 or goodid > 6):
print('What? Sorry, you can not buy anything today. This may affect your membership'
'(A **month** of continuous shopping)')
day = 0
continue
else:
pr = goodlist[goodid][1]
if (goodid == 0):
cnt += 1
if (cnt > 6):
print('You eat too much 1da! What about trying something other?')
if (cnt == 10):
print('You eat too much 1da and You triggered the hidden task: Get membership!')
if (money >= pr):
money -= pr
day += 1
print('Thanks!')
else:
print('Please earn more!')
if (day >= 30 and cnt >= 10):
print('Dear Membership', name)
print('I will show you my Recommendation system. It contains A super AI and I test it myself!')
print('But before I show that, what about a easy game?')
print('Your answer is(Y/N):')
tmpans = getinput()
if (tmpans == 'Y'):
print('Great! You like it!')
else:
print('You say No, but I believe you actually like it!')
print('Here is the game, please find my score(integer) to those goods which have 0 score:')
N = 8
M = 14
K = 3
P = np.random.randint(5, size=(N, K)) + 1
Q = np.random.randint(5, size=(M, K)) + 1
R = np.dot(P, Q.T)
anslist = R.tolist()[0]
ans = ''
for i in anslist:
ans += str(i)
md5hash = hashlib.md5(ans.encode())
md5 = md5hash.hexdigest()
locs = random.sample(range(0, 14), 6)
for i in locs:
R[0][i] = 0.0
mat = R.tolist()
print('beginmatrix')
print(mat)
print('endmatirx')
print('where row stand for user and col stand for goods')
print('The good and user embedding dim are both 3!')
print('The flag is md5(first row)')
print('Example: if the first row is [14 13 9 22 20 25 14 27 20 15 19 10 32 21]'
' md5(141392220251427201519103221)==59d25d2c3cc2bb1d27f550329d35f5a5\n'
'So, the answer is 59d25d2c3cc2bb1d27f550329d35f5a5')
print('Now, what is your answer?')
player_ans = getinput()
if (md5 == player_ans):
print('flag{a2b035c8_congratulations+7618=on=528f1b1_solving_this>814464a4c6812<problem:D}')
if __name__ == '__main__':
Main()
exp
#This exp references the link https://blog.csdn.net/weixin_43164078/article/details/124278175 implementation
from pwn import *
from math import *
import numpy as np
import hashlib
import ast
context.log_level= 'debug'
def MF(R,P,Q,K,aplha,beta,steps):
'''
:param R: user-item rating matrix m*n
:param P: user's decomposition matrix m*k
:param Q: item's tap matrix m*k
:param K: dimension of the hidden vector
:param aplha: learning rate
:param beta: regularization parameter
:param steps:
:return:
'''
print('Start decomposing the original matrix')
Q=Q.T
result=[]
#Start training Update parameters Calculate loss
#Update parameters using gradient descent
print('Start Training')
for step in range(steps):
''''''
for i in range(len(R)):
for j in range(len(R[i])):
eij=R[i][j]-np.dot(P[i,:],Q[:,j])
for k in range(K):
if R[i][j]>0:
#update parameters
P[i][k]=P[i][k]+aplha*(2*eij*Q[k][j]-beta*P[i][k])
Q[k][j]=Q[k][j]+aplha*(2*eij*P[i][k]-beta*Q[k][j])
eR=np.dot(P,Q)
#Calculate the loss value
e=0
for i in range(len(R)):
for j in range(len(R[i])):
if R[i][j] > 0:
e = e + pow(R[i][j] - np.dot(P[i, :], Q[:, j]), 2)
for k in range(K):
e = e + (beta / 2) * (pow(P[i][k], 2) + pow(Q[k][j], 2))
result.append(e)
if e < 0.001:
break
print('Training Finshed')
return P, Q.T, result
r=remote("127.0.0.1",11409)
r.recvuntil(b'May I know your name(**less than 50 ascii**), please?')
r.sendline(b'Bob')
for i in range(10):
r.recvuntil(b'Please input your good number:')
r.sendline(b'0')
for i in range(20):
r.recvuntil(b'Please input your good number:')
r.sendline(b'3')
r.recvuntil(b'Your answer is(Y/N):')
r.sendline('Y')
r.recvuntil(b'beginmatrix\n')
R=r.recvline().decode().replace(' ','').replace('\n','')
R=np.array(ast.literal_eval(R))
N,M,K=8,14,3
P=np.random.rand(N,K)
Q=np.random.rand(M,K)
nP,nQ,result=MF(R,P,Q,K,aplha=0.0002,beta=0.02,steps=5000)
R_MF=np.dot(nP,nQ.T)
md5str=''
for i in range(M):
md5str+=str(round(R_MF[0][i]))
md5hash=hashlib.md5(md5str.encode())
md5=md5hash.hexdigest()
r.recvuntil(b'Now, what is your answer?')
r.sendline(md5)
flag=r.recvline()
print(bytes.decode(flag))
r.interactive()