7th XCTF-Final Shop(an AI game)

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

您可以通过下列交互获得一系列提示:

  1. 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!!!

  2. 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)

  3. buy 10 1da–>

    You eat too much 1da and You triggered the hidden task: Get membership!

  4. 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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值