Loading

2022.7DASCTF re wp

RE

完全忘记这个比赛 和同学玩的很开心)

所有全是赛后做的)

隐秘的角落

非常简单的签到题 如果我不发病的话

动调拿到enc

image-20220726001534956

或者静态拿enc 记得有^0x23

image-20220726001551547

看函数名看出来是rc4算法 别管啥玩意key了

传进去"\x00"*36

image-20220726001655326

image-20220726001738052

拿到加密后结果 由于rc4是异或算法 0^key==key

所以现在的值就是key 直接异或即可

enc = [251, 198, 166, 157, 196, 219, 123, 86, 182, 70, 166, 192, 133, 100, 122, 154, 55, 76, 16, 150, 233, 167, 40, 196,
       177, 45, 241, 222, 71, 59, 181, 243, 44, 125, 103, 29]

key = [0xce, 0xf0, 0xc3, 0xa5, 0xf7, 0xed, 0x42, 0x62,
       0x9b, 0x20, 0x9f, 0xf7, 0xb3, 0x49, 0x4b, 0xab,
       0x52, 0x2e, 0x3d, 0xf4, 0xda, 0x93, 0x1b, 0xe9,
       0xd7, 0x4c, 0x97, 0xb8, 0x24, 0x09, 0x85, 0xc2,
       0x4f, 0x45, 0x02, 0x2d, 0x00, 0x00, 0x00, 0x00, ]
for i in range(36):
       print(chr(enc[i] ^ key[i]), end="")

56e83694-f976-11eb-b343-faffc201c8e0

输入程序后 记得按提示md5一下

DASCTF{9e1963bbbb1285b993c862a5a6f12604}

fatanstic_maze

和上次stargate好像) 不过这次用另一种方式做

连上靶机后先爆破sha256

用了个go语言的)(

./test.exe sha256尾 值

package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"runtime"
	"sync"
	"os"
)

var (
	chars     = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")
	tail      = []byte("SUex0zeSOI7DilNj")
	result, _ = hex.DecodeString("b5bbdab6b117ece3e45ca60ecf2c666e7a5ee1bcbb9596c1e06c7e7995c1ee8d")
	wg        sync.WaitGroup
)

func sha(s []byte) {
	for _, ch1 := range s {
		for _, ch2 := range chars {
			for _, ch3 := range chars {
				for _, ch4 := range chars {
					head := []byte{ch1, ch2, ch3, ch4}
					h := sha256.New()
					h.Write(head)
					h.Write(tail)
					if bytes.Equal(h.Sum(nil), result) {
						fmt.Println(string(head))
					}
				}
			}
		}
	}
	wg.Done()
}

func main() {
	args := os.Args
	tail = []byte(args[1])
	result, _ = hex.DecodeString(args[2])
	// fmt.Println(string(tail))
	// fmt.Println(string(result))
	threads := runtime.NumCPU() // 获取cpu逻辑核心数(包括超线程)
	snum := len(chars) / threads
	sthreads := threads*(1+snum) - len(chars)
	wg.Add(threads)
	for i := 0; i < threads; i++ {
		if i < sthreads {
			go sha(chars[snum*i : snum*(i+1)])
		} else {
			base := snum * sthreads
			go sha(chars[base+(snum+1)*(i-sthreads) : base+(snum+1)*(i-sthreads+1)])
		}
	}
	wg.Wait()
}

然后是pwntools脚本编写

import os
import time

from  pwn import  *
# context(log_level="DEBUG")
ppp=remote('node4.buuoj.cn',27564)
tem=ppp.recvuntil(b'[+] Plz Tell Me XXXX :')

tail=tem.decode()[18:].split(")")[0]
sha256=tem.decode()[18:].split("== ")[1].replace("\'","")
#这是个go写个sha256爆破
ccc=r".\test.exe "+tail+" "+sha256
eee=os.popen(ccc).read()


ppp.send(str(eee).encode())
ppp.recvuntil(b"a map :")
map=ppp.recvuntil(b"That's all")
with open("mappp",'wb') as f:
    f.write(base64.b64decode(map))

把文件写入mappp中

IDA小分析一下

image-20220726141418850

main进入function_0中 然后通过case数字来回在各个函数中跳 每走一个函数tmp++

最后到达function_1000时tmp要为1000

image-20220726141529657

我们先找到路径 使用idapython!

这里是ida7.7 内置python3.8 记得给内置的python装一下numpy什么的库

用idapython的各个api得到asm,简单匹配一下得到可达关系

image-20220726142140085

import idaapi
import idautils
import idc
def fuckfuncnew():
    all_funcs = idautils.Functions()
    indexdddd = {}
    dddd={}
    for fn in all_funcs:
        #fn是个int 就是这个函数的地址
        func_name = idc.get_func_name(fn)
        if (not func_name.startswith("function_")):
            continue
        if func_name.startswith("function_1000"):
            continue
       	#获得当前函数的起始与结束
        start = idc.get_func_attr(fn, FUNCATTR_START)
        end = idc.get_func_attr(fn, FUNCATTR_END)
        
        curr_addr = start
        func_index=int(func_name.split("_")[-1])
        #我用indexdddd字典表示函数间的可达关系 下标为0的表示case 1进入
        indexdddd[func_index]=[]
        #dddd没用到
        dddd[func_name] = []
        #逐句遍历当前函数asm
        while curr_addr <= end:
            # print(hex(curr_addr),idc.GetDisasm(curr_addr))
            #当前地址的汇编
            asmmm = idc.GetDisasm(curr_addr)
            #print(asmmm)
            import re
            casein = re.match(".*case [0-9]{1,5}", asmmm)
            if casein and ("case 0" not in asmmm):
                index = asmmm.split()[-1]
                nextfunc = idc.GetDisasm(idc.next_head(curr_addr, end)).split()[1]
                nextindex=int(nextfunc.split("_")[-1])
                indexdddd[func_index].append(nextindex)
                dddd[func_name].append(nextfunc)
                # print(index, nextfunc)
            curr_addr = idc.next_head(curr_addr, end)
    # return dddd
    return indexdddd

a=fuckfuncnew()
# b=fuckfuncori()
#求有向无权图最短路径 networkx
import networkx as nx
G = nx.DiGraph()
for i in range(0,1001):
    G.add_node(i)
for x in a.keys():
    for t in a[x]:
        G.add_edge(x,t)

p=nx.shortest_path(G,source=0,target=1000)
#p就是最短路径 但是题目要求步数为1000步 观察程序发现输入不在case表中的话 会回到function_0 利用这一点刷步数
f=[666666]*(1000-len(p))

for index in range(len(p)-1):
    
    f.append(a[p[index]].index(p[index+1])+1)
#这个为了当回车用
f.append("")
#这个文件名只要和下面的一样就行)
with open(r"D:\CTF\2022.7DAS\RE\fatanstic_maze\ffff.txt","w")as filee:
    filee.write("\n".join(list(map(str,f))))
print(p)




计算出来的最短路径

image-20220726142457468

接下来回到pwntools的脚本中

import os
import time

from  pwn import  *
# context(log_level="DEBUG")
ppp=remote('node4.buuoj.cn',27564)
tem=ppp.recvuntil(b'[+] Plz Tell Me XXXX :')

tail=tem.decode()[18:].split(")")[0]
sha256=tem.decode()[18:].split("== ")[1].replace("\'","")
#这是个go写个sha256爆破
ccc=r".\test.exe "+tail+" "+sha256
eee=os.popen(ccc).read()


ppp.send(str(eee).encode())
ppp.recvuntil(b"a map :")
map=ppp.recvuntil(b"That's all")
with open("mappp",'wb') as f:
    f.write(base64.b64decode(map))
#暂停
print("请去idapython里面跑一下脚本,跑完按回车")
input()
with open(r"D:\CTF\2022.7DAS\RE\fatanstic_maze\ffff.txt","r")as fileee:
    t=fileee.read()
ppp.send(t)
ppp.interactive()

image-20220726142627858

操作流是先打开ida64备好

先跑pwntools脚本 出现提示信息后 ida分析mappp文件 等分析完后alt+f7 选择idapython脚本 run 然后去pwntools脚本里按回车

得到flag!

ezGO

rsa题目 移步别的师傅wp 请(

)

e4sy_mix

VM题 还是调用so

先点开主函数 小修一下变量类型

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int i; // [rsp+8h] [rbp-98h]
  int j; // [rsp+Ch] [rbp-94h]
  int k; // [rsp+10h] [rbp-90h]
  int V[2]; // [rsp+18h] [rbp-88h] BYREF
  int key[4]; // [rsp+20h] [rbp-80h] BYREF
  int tem[8]; // [rsp+30h] [rbp-70h] BYREF
  char input_[65]; // [rsp+50h] [rbp-50h] BYREF
  unsigned __int64 v11; // [rsp+98h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  memset(input_, 0, sizeof(input_));
  memset(tem, 0, sizeof(tem));
  *V = 0LL;
  key[0] = 0x21728857;
  key[1] = 0xB5077292;
  key[2] = 0xE737DC2B;
  key[3] = 0x4CC17426;
  __isoc99_scanf("%s", input_);
  if ( strlen(input_) != 64 )
    return 0LL;
  for ( i = 0; i <= 7; ++i )
  {
    for ( j = 0; j <= 7; ++j )
      tem[i] |= (input_[8 * i + j] - '0') << (4 * j);
  }
  for ( k = 0; k <= 3; ++k )
  {
    V[0] = tem[2 * k];
    V[1] = tem[2 * k + 1];
    TEA(0x20u, V, key);
    tem[2 * k] = V[0];
    tem[2 * k + 1] = V[1];
  }
  if ( vm(tem, 8LL) )
    output_flag(input_);
  return 0LL;
}

简单来说就是输入flag 经过一个小变换 然后跑一圈TEA加密 将加密后结果送入vm函数中

所以重点看vm 打开so
看一下函数内容 写opcode解析器即可

posted @ 2022-07-27 15:13  FW_ltlly  阅读(223)  评论(0编辑  收藏  举报