[XCTF-Reverse] 41-44

41,SHCTF-2017_crackme

用北极星加的壳,去壳以后就一眼明白了,就是个异或

网上讲了些手工去壳的方法,没学会。直接用的工具。

  printf("Please Input Flag:");
  gets_s(&Buf, 0x2Cu);
  if ( strlen(&Buf) == 42 )
  {
    v4 = 0;
    while ( (*(&Buf + v4) ^ byte_402130[v4 % 16]) == dword_402150[v4] )
    {
      if ( ++v4 >= 42 )
      {
        printf("right!\n");
        goto LABEL_8;
      }
    }
    printf("error!\n");
LABEL_8:
    result = 0;
  }

#exeinfope 查壳:nsPack ver.3.x-4.1 reg by North Star  [ Size Of Code = 00 Kb - FIX IT ! NSTD ! ] 

a = [0x12,    4,    8, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A, 
     0x10, 0x67,    0, 0x41,    0,    1, 0x46, 0x5A, 0x44, 0x42, 
     0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F,
      0x2,    1, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68, 0x5B, 0x12]
b = b'this_is_not_flag'

print(''.join([chr(b[i%16]^a[i]) for i in range(42)]))
#flag{59b8ed8f-af22-11e7-bb4a-3cf862d1ee75}

42,梅津美治郎

ida打开,没有啥保护很容易就过一第关,但第2关入口看不到,有个特殊的函数

  strcpy(v8, "r0b0RUlez!");
  dword_40AD94 = (int)&v9;
  dword_40ADA0 = (int)&v49;
  dword_40AD8C = (char *)&v40;
  dword_40AD90 = (char *)&v31;
  dword_40AD98 = (int)&v28;
  lpProcName = (LPCSTR)&v17;
  lpModuleName = (LPCSTR)&v24;
  dword_40ADA4 = (char *)&v10;
  sub_401500(0);
  v3 = lpProcName;
  v4 = GetModuleHandleA(lpModuleName);
  v5 = (void (__stdcall *)(HMODULE, LPCSTR))GetProcAddress(v4, v3);
  v5((HMODULE)1, (LPCSTR)sub_40157F);     //<----- 第一关通过后会进入sub_4015ea然后调用sub_40157f进入第2关
  puts(dword_40AD8C);
  scanf("%20s", &v7);
  if ( !strcmp(&v7, v8) )
  {
    puts("You passed level1!");
    sub_4015EA(0);
  }

第2关只是个简单的异或,在比较前下断点,看内存

ebp+c:0x28f7b4->0x28fdcc->'u1nnf2lg'

得到第2个串,然后还原(两段用下划线连上,这个没有提示)

a1 = b'r0b0RUlez!'
a2 = b'u1nnf2lg'
a2 = [i^2 for i in a2]
print(a1 +b'_'+ bytes(a2))
#b'r0b0RUlez!_w3lld0ne'
#flag{r0b0RUlez!_w3lld0ne}

43,2019“嘉韦思杯”上海市网络安全邀请赛_76号

这个跟前边41动态调试的类似,只是不用调试。

一开始不能反编译,但大概能看明白,一直调用到sub_8048580 检查函数

这个函数是个大switch v2作序号,从0到N,序号和字符对应的就是那个字符。

两个小坑,第1个出现的10表示回车,这里的序号是13说明前边处理13个字符(逻辑上不大成立)

        case 10:                                // 回车结束 13
          return v2 == 13 && v28 != 0;          // 总共13,12在这里return

第2个小坑就是,既然总共有13个那到第13个就该返回了,第13个字符有两种情况一种是返回的一种是不返回继续的,应该选返回的那个

        case 54:      //这个看上去正确,但没有返回,不选
          if ( v2 != 12 || !v35 )
            return 0;
          v2 = 13;
          continue;
......
        case 107:
          return v2 == 12 && v14 != 0;    //最后一位选这个

最后把这些连一起

a = bytes([48, 57, 118, 100, 102, 55, 119, 101, 102, 105, 106, 98, 107])
print(a)
#09vdf7wefijbk
#flag{09vdf7wefijbk}

44,Hack-you-2014_APK逆向2

这个题有点怪,这不是个apk是个.net的exe文件

用ILSpy打开有3个小函数。主程序就是把一串的字母逐个从第2个串里找偏移然后16进制打印出来

private static void Main(string[] args)
{
	string hostname = "127.0.0.1";
	int port = 31337;
	TcpClient tcpClient = new TcpClient();
	try
	{
		Console.WriteLine("Connecting...");
		tcpClient.Connect(hostname, port);
	}
	catch (Exception)
	{
		Console.WriteLine("Cannot connect!\nFail!");
		return;
	}
	Socket client = tcpClient.Client;
	string text = "Super Secret Key";
	string text2 = read();
	client.Send(Encoding.ASCII.GetBytes("CTF{"));
	string text3 = text;
	foreach (char x in text3)
	{
		client.Send(Encoding.ASCII.GetBytes(search(x, text2)));
	}
	client.Send(Encoding.ASCII.GetBytes("}"));
	client.Close();
	tcpClient.Close();
	Console.WriteLine("Success!");
}

第2个是这个偏移怎么计算

private static string search(char x, string text)
{
	int length = text.Length;
	for (int i = 0; i < length; i++)
	{
		if (x == text[i])
		{
			int num = i * 1337 % 256;
			return Convert.ToString(num, 16).PadLeft(2, '0');
		}
	}
	return "??";
}

关键是这第3个串,调用的read但并不是平常用的read而是自己写的一个,把程序本身读进来当字符串2

private static string search(char x, string text)
{
	int length = text.Length;
	for (int i = 0; i < length; i++)
	{
		if (x == text[i])
		{
			int num = i * 1337 % 256;
			return Convert.ToString(num, 16).PadLeft(2, '0');
		}
	}
	return "??";
}

看上去就行了

a = b"Super Secret Key"
text = open('4122e391e1574335907f8e2c4f438d0e.exe', 'rb').read()
b = ''.join([hex(text.index(i) * 1337 % 256)[2:].rjust(2, '0') for i in a])
print('CTF{'+b+'}')
#CTF{7eb67b0bb4427e0b43b40b6042a00b8e}
#CTF{7eb67b0bb4427e0b43b40b6042670b55}  <----??

但运行结果与网上搜的差两个字符,不清楚为什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值