首页
社区
课程
招聘
[原创]Riijj – Crackme 15 (实验1)
发表于: 2009-10-10 00:22 16274

[原创]Riijj – Crackme 15 (实验1)

2009-10-10 00:22
16274
收藏
免费 7
支持
分享
最新回复 (32)
雪    币: 8209
活跃值: (4518)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
26
先按国际惯例辣手摧花
原本想写脚本去花,可是我已经忘记脚本的语法了,只好用C来写:
void riijj_junkfix()
{
	DWORD dwTmp;
	DWORD Addr;
	DWORD AddrE;
	DWORD CallAddr;

	Addr = 0x401000;
	AddrE = 0x403E00;
	VirtualProtect((LPVOID)Addr,AddrE-Addr,PAGE_EXECUTE_READWRITE,&dwTmp);

	while (Addr < AddrE)
	{
		if ((*(DWORD *)Addr == 0x058DED39) && (*(BYTE *)(Addr+8) == 0x74))
		{
			dwTmp = *(BYTE *)(Addr+9);
			CallAddr = *(DWORD *)(Addr+4) + *(DWORD *)(Addr+dwTmp+12);
			if (*(WORD *)(Addr+dwTmp+16) == 0xD0FF)
			{
				memset((LPVOID)Addr,0x90,dwTmp+13);
				*(BYTE *)(Addr+dwTmp+13) = 0xE8;
				*(DWORD *)(Addr+dwTmp+14) = CallAddr - (Addr+dwTmp+18);
				Addr += dwTmp+18;
			}
			else if ((*(BYTE *)(Addr+dwTmp+16) == 0x68) && (*(DWORD *)(Addr+dwTmp+17) == (Addr+dwTmp+23)))
			{
				memset((LPVOID)Addr,0x90,(dwTmp+18));
				*(BYTE *)(Addr+dwTmp+18) = 0xE8;
				*(DWORD *)(Addr+dwTmp+19) = CallAddr - (Addr+dwTmp+23);
				Addr += (dwTmp+23);
			}
			else
			{
				Addr++;
			}
		}
		else if ((*(BYTE *)Addr == 0x74) && (*(BYTE *)(Addr+2) == 0x75) && (*(BYTE *)(Addr+1) - *(BYTE *)(Addr+3) == 2))
		{
			dwTmp = *(BYTE *)(Addr+3)+4;
			memset((LPVOID)Addr,0x90,dwTmp);
			Addr += dwTmp;
		}
		else
		{
			Addr++;
		}
	}
}

我是用LPK注进去执行这段代码的来修复的,执行完以后应该把花指令去光了,修好了保存一下文件,只剩下那些jmp来jmp去的东西了,这些jmp应该也是可以修复的,我短时间写不好,所以放弃这个想法。
还有一种选择是直接写idc脚本,我想有这个能力的人没必要看我这个帖子了。

此处无花胜有花应该就是指现在的感受了
找到注册检查函数入口40263B,方法我也不会,我是胡乱下断点命中的,自己尝试,也许可以断在GetDlgItemTextA从堆栈里找返回地址。
把修好的文件用ida打开,在函数40263B处F5,Hex-Rays很强大,无视那些jmp
int __cdecl sub_40263B()
{
  int result; // eax@1
  unsigned int v1; // ecx@11
  signed int v2; // [sp+4Ch] [bp-F0h]@1
  signed int v3; // [sp+48h] [bp-F4h]@1
  unsigned int v4; // [sp+44h] [bp-F8h]@1
  int v5; // [sp+F0h] [bp-4Ch]@1
  unsigned int v6; // [sp+40h] [bp-FCh]@1
  int v7; // [sp+B0h] [bp-8Ch]@1
  UINT v8; // [sp+3Ch] [bp-100h]@1
  unsigned int v9; // [sp+2Ch] [bp-110h]@1
  unsigned int v10; // [sp+38h] [bp-104h]@2
  int v11; // [sp+130h] [bp-Ch]@2
  unsigned int v12; // [sp+20h] [bp-11Ch]@9
  unsigned int v13; // [sp+30h] [bp-10Ch]@11
  unsigned int v14; // [sp+24h] [bp-118h]@11
  unsigned int v15; // [sp+28h] [bp-114h]@11
  unsigned int v16; // [sp+34h] [bp-108h]@11
  unsigned int *v17; // [sp+18h] [bp-124h]@15
  int v18; // [sp+50h] [bp-ECh]@24
  int v19; // [sp+1Ch] [bp-120h]@31

  v2 = 7823;
  v3 = 97157;
  v4 = 457;
  v6 = GetDlgItemTextA((HWND)dword_406078, 1000, (CHAR *)&v5, 50);
  v8 = GetDlgItemTextA((HWND)dword_406078, 1001, (CHAR *)&v7, 50);
  result = 97157;
  v9 = 97157;
  if ( v6 && v8 > 0x13 )
  {
    v10 = 0;
    while ( v10 <= 0x31 )
    {
      v19 = v2 * v9;
      v17 = &v6;
      v9 = v2 * v9 % v4 + *((_BYTE *)&v5 + v10 % v6);
      *((_BYTE *)&v11 + v10++ - 192) = v9;
    }
    v12 = 1;
    v10 = 0;
    while ( v10 < v6 )
    {
      if ( v10 & 1 )
        v12 %= (unsigned int)*((_BYTE *)&v11 + v10 - 64);
      else
        v12 *= *((_BYTE *)&v11 + v10 - 64);
      ++v10;
    }
    v9 = v3;
    memset(&v18, 0, 0x1Eu);
    v10 = 0;
    while ( v10 <= 0x13 )
    {
      v1 = v12 * *((_BYTE *)&v11 + v10 - 192);
      v13 = v1 % 0x32;
      v14 = *((_BYTE *)&v11 + v1 % 0x32 - 192);
      v15 = v14;
      v16 = 0;
      while ( v16 < v15 )
      {
        v17 = &v4;
        v9 = v2 * v9 % v4 ^ *((_BYTE *)&v11 + v10 - 192);
        ++v16;
      }
      *((_BYTE *)&v11 + v10++ - 224) = v9 % 0x1A + 65;
    }
    v10 = 0;
    while ( v10 <= 0x13 )
    {
      result = *((_BYTE *)&v11 + v10 - 128);
      if ( (_BYTE)result != *((_BYTE *)&v11 + v10 - 224) )
        return result;
      ++v10;
    }
    result = sub_402351();
  }
  return result;
}

402351处也顺便F5看看:
int __cdecl sub_402351()
{
  return MessageBoxA((HWND)dword_406068, "Registration successful !", "Riijj crackme 15b1", 0);
}


这样流程应该可以看清楚了,怎么爆破已经不重要了,看心情自由发挥
如果你是个无赖就这样:

4017D4  call    40263B
改成
4017D4  call    402351

如果你比较传统就把
0040266A   JNZ     0040302B
整行nop掉

如果你想搞得神秘一点
就把sub_40263B整理一下,重新编译一份贴回去,要调整一下GetDlgItemTextA的地址,call memset和call 402351的偏移,然后再随便你怎么爆

其实这个crackme是明码比较,爆破纯属娱乐。

最后借机说点题外话:
zenghw的不情之请贴已经让版主帮忙移到水区了,首先感谢大家的支持,我只能以具体程序就事论事地与大家交流,我都是现学现卖的,用完就忘的,大部分都是靠google来的,解决一个问题就扔掉了,基本不会花时间去研究原理的。
就比如本例中的crackme,过些天再拿出来,我还是要重新看,也许我会选择用od脚本去花,脚本语法忘了,我就看帮助再学一遍就是了,再过些天再遇到这个crackme也许我会有兴趣学一下idc脚本来去花,所以同一个程序在没开始分析之前,我自己都不知道可能怎么去分析它,而且中途遇到困难也会随时改变想法。
对于我来说基础就是看到一行汇编代码知道它执行完以后寄存器状态会产生哪些变化,尽量记住大部分16进制机器码;几行指令组合起来是什么意思就要每个人花时间去积累了,可能像被单词一样。
2009-10-13 12:02
0
雪    币: 347
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
27
对于我来说基础就是看到一行汇编代码知道它执行完以后寄存器状态会产生哪些变化,尽量记住大部分16进制机器码;几行指令组合起来是什么意思就要每个人花时间去积累了,可能像被单词一样


大沙发,听君一席话胜读十年书,实践出真理,努力学习,积极支持CCFER(差点被秒杀了)
2009-10-13 12:15
0
雪    币: 2319
活跃值: (565)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
28
多谢 ccfer 的认真分析,大家获益了

希望我能够写出 beta 2,再给大家尝试
2009-10-13 21:33
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
嘿嘿, 第一次独立爆破成功, 发上来纪念一下。
附带一个非常傻瓜的od脚本, 可以去掉花指令。
开始以为一路f8不用理会花指令来着, 后来真是晕了,
鼓起勇气弄了这个傻瓜去花脚本。没想到真得有效果,
轨迹一下子清晰了。

上传的版本修改了多个跳转, 后来理顺一下只需在这句jmp即可。
00402C39     /0F87 EA010000 ja      00402E29 ;  已经比较完了20个字符则跳到注册成功

感谢riijj老兄的辛苦劳动!
上传的附件:
2009-10-14 20:59
0
雪    币: 183
活跃值: (1218)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
30
一句一个跳转

怎么跟啊
2009-11-5 12:57
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
刚开始学习啊,问个问题, 这个花指令是编译的时候就加进去了还是exe文件修改的?
2009-11-13 10:35
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
32
在问个问题,是不是跟这种代码就是不停的跳来跳去
2009-11-16 10:21
0
雪    币: 269
活跃值: (906)
能力值: ( LV12,RANK:345 )
在线值:
发帖
回帖
粉丝
33
name:1111111111
key:JEVMKWFZJRXSUPVWGDJL
上传的附件:
2015-7-24 14:36
0
游客
登录 | 注册 方可回帖
返回
//