首页
社区
课程
招聘
[旧帖] [原创]纯汇编CM[邀请码已发] 0.00雪花
发表于: 2010-2-4 00:31 4654

[旧帖] [原创]纯汇编CM[邀请码已发] 0.00雪花

2010-2-4 00:31
4654
标 题: 【原创】纯汇编CM
作 者: Crakme
时 间: 2010-02-04,00:31
链 接: http://bbs.pediy.com/showthread.php?t=106605

,我也来个像样的开头,把标题、作者、时间、链接都写上。我看到大牛们的精华帖就是这个样子的,我也来仿照一下。虽然我是很菜的菜鸟, 菜鸟无罪。

之所以写这个CM( 前几天才知道CM是crackme的缩写,我的ID是Crakme,有点相似吧),有那么一点点故事。我放寒假在家,正好我哥也回来了,而且还特地带了三本书给我。《WINDOWS环境下32位汇编语言程序设计》、《驱动开发技术详解》、《加密与解密》,并且跟我说我能把这三本书都认真的学完了就是电脑高手了。我自认为自己电脑学的还可以了,至少在同学们当中算是高手,干吗去啃那么厚的书。当我拿着书随便翻阅了一下, 这根本就是天书嘛。本以为C语言对我来说很容易,在《驱动开发技术详解》里看到程序代码函数开头都加个"NTSTATUS",感觉莫名其妙,那两本就更不用说了,汇编代码满天飞,晕了。我哥看我懵了,接着就开始对我长篇大论的说教。我一句都没听进去,想想他是研究生,我才大二,他肯定比我厉害啦,再者我们课堂上老师从没教过这个,我怎么会知道呢。郁闷了一阵,心里挺不服的,不过确实让自己刚觉到好渺小,大学学了一年半就学了个C语言,还学会了玩魔兽。最后还是沉下心来了,去问我哥加密与解密该怎么学。  我本以为我哥会手把手的教我,没想到就只告诉我,这个你要自学,那三本书你就将就着看,记得每天去看雪论坛逛逛。我晕,难道令我崇拜的哥就是这么学出来的?于是屁颠屁颠的去开电脑上网,通过搜索来到了看雪论坛,接着注册了个帐号。,又晕了,普通会员是要邀请码的。又屁颠屁颠的跑我哥旁边,要他发个邀请码给我,我哥竟然不给,要我自己靠自己本事去争取。看了大半天的论坛,除了初学者原地、职场风云、未分类版块的内容能看懂外,其它版块的帖子基本上看不懂  

我幼小的心灵真的受打击了

最后决定我要写CM,让后我自己crack,虽然这样有些矛盾,不过我想到了一句话“在攻与防的对立统一中寻求突破”。这是我以前看《黑客防线》里的一句话,没想到在这里用上了。   可是我对汇编基本上不了解,于是用最快的速度把《WINDOWS环境下32位汇编语言程序设计》这本书翻了一遍,在论坛上搜到了REDASM这个工具。说来也巧,REDASM里面有KeyGen的代码模板,于是依葫芦画瓢写下了这个CM。好像KeyGen的代码模板的作者CCDebuger还是论坛里的前辈,在《加密与解密》的书上看到了他的名字,在这里先谢谢了。

这只是我的第一个CM,也是我第一次在看雪发帖。这个CM的技术我就不说了,没啥技术,个人感觉很烂,不过我的CM会越写越好的。虽然现在对壳还不清楚,我也给我的CM加了个壳。我看着论坛里的帖子,自己试了下脱壳,弄了半天竟然还是不会。   去找我哥,他给我演示了一遍,大概20秒就脱了,没看清咋回事。再要求演示了一遍,还是没看明白  第三遍总算知道怎么点鼠标,选哪个菜单弄了,原理还是不明白。我哥说是ESP定律, 脱壳还有定律,打算花点时间学一下。我想我会坚持的,因为看雪真的是个很好的论坛,有很多的学习资料,许多的人都很热心帮助,无私奉献。因为看雪的强大,我想我会很快变得强大的。

我还是个很菜的菜鸟,我希望能有人愿意跟我一起探讨、学习。

CM的界面


加壳的CM
crackme01.exe.rar

REDASM工程源文件
crackme01.src.rar

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (44)
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
忘记了,临时会员下载需要KX,就把代码贴出来了
以后发CM时,源码会在CM发布后的第二天发布

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include crackme01.inc

.code

start:

	invoke GetModuleHandle,NULL
	mov	hInstance,eax

        invoke InitCommonControls
	invoke DialogBoxParam,hInstance,MAIN_DIALOG,NULL,addr DlgProc,NULL
	invoke ExitProcess,0

AboutProc proc hAWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
	
	mov	eax,uMsg
	.if eax == WM_INITDIALOG
		invoke LoadIcon,hInstance,ICON_MAIN
		invoke SendMessage, hAWin, WM_SETICON, ICON_SMALL, eax
	.elseif eax == WM_COMMAND
		mov eax,wParam
		.if eax == IDC_OK
			invoke EndDialog,hAWin,0
		.endif	
	.elseif eax == WM_CLOSE
	invoke EndDialog,hAWin,NULL
	.else
		mov		eax,FALSE
		ret
	.endif
	mov		eax,TRUE
	ret

AboutProc endp

DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

	mov	eax,uMsg
	.if eax == WM_INITDIALOG
		invoke LoadIcon,hInstance,ICON_MAIN
		invoke SendMessage, hWin, WM_SETICON, ICON_SMALL, eax
		pop edi
	.elseif eax == WM_COMMAND
		mov eax,wParam
		.if eax == IDC_TEST
			invoke GetDlgItemText,hWin,IDC_ID, addr id, 255
			.if eax == 0
				invoke SetDlgItemText,hWin,IDC_CODE,addr error
				ret
			.endif
			invoke GetDlgItemText,hWin,IDC_CODE, addr code, 255
			.if eax == 0
				invoke SetDlgItemText,hWin,IDC_CODE,addr errorserial
				ret
			.endif
			invoke lstrcat,addr serial,addr id
			invoke lstrcmp,addr serial,addr code
			.if eax==0
				invoke MessageBox,NULL,addr szCongratulation,addr szCaption,MB_OK
				invoke EndDialog,hWin,0
			.else 
				invoke EndDialog,hWin,0
			.endif	
		.elseif eax == IDC_ABOUT
			invoke CreateDialogParam,hInstance,DLG_ABOUT,hWin,addr AboutProc,FALSE
		.elseif eax == IDC_EXIT
				invoke    EndDialog,hWin,NULL
		.endif
	.elseif eax == WM_CLOSE
		invoke EndDialog,hWin,0
	.else
		mov		eax,FALSE
		ret
	.endif
	mov eax,TRUE
	ret

DlgProc endp

end start


INC文件内容
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
 

DlgProc			PROTO	:HWND,:UINT,:WPARAM,:LPARAM

.const

MAIN_DIALOG		equ 101
DLG_ABOUT		equ 102
IDC_ID  			equ 1001
IDC_CODE		equ 1002
IDC_TEST			equ 1005
IDC_EXIT			equ 1006
IDC_ABOUT		equ 1007
IDC_OK			equ 1008
ICON_MAIN		equ 10
.data

error			db 'Please input ID!',0
errorserial		db 'Please input your serial!',0
szCaption  		db 'Congratulation',0
szCongratulation  		db 'You are good!',0
serial			db 'pediy',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;#########################################################################

.data?

hInstance			dd ?
id                   		db 21 dup(?)
code			dd ?
;#########################################################################
2010-2-4 00:38
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
用REDASM编译后得到可执行文件大小为8KB,加壳后变成12KB,再脱壳变成41KB了
  还是汇编好
2010-2-4 09:51
0
雪    币: 146
活跃值: (182)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
4
呵呵呵,这三本看了2本了
2010-2-4 09:54
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
你看了多长时间啊?收获应该很大吧?
2010-2-4 09:57
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
呵呵,楼主的贴子好深奥啊,!
2010-2-4 09:58
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
  不是打击我吧。我啥技术都没谈,哪来的深奥啊。可能是我的文字功底不好,句子有些不顺畅。
2010-2-4 10:03
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
8
源码都贴出来了还玩什么?
2010-2-4 10:58
0
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
用什么脱得壳啊?OD还是什么?
2010-2-4 11:07
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
我是来膜拜楼主ID的。。。。。。。
2010-2-4 11:16
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
  这个CM不是用来玩的,太容易了,注册码算法才一个语句。
只是看看用汇编怎么写CM,我还是个初学者,请大家给我指点指点。
2010-2-4 11:19
0
雪    币: 88
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
od就可以了,练习手脱
2010-2-4 11:20
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
当然是OD啦。用脱壳机那就没啥意义了
2010-2-4 11:20
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
   ID也能膜拜啊
2010-2-4 11:22
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
15
你哥应该可以买邀请码给你.
之前注册的都有200kx
2010-2-4 11:26
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
  我哥他不给啊,他的ID有将近1000KX
再者我现在想通过我自己的努力获得。
2010-2-4 11:29
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
17
LZ的老哥哪一位啊,爆料一下
2010-2-4 11:37
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
我哥是个潜水艇啊。没啥名气
2010-2-4 12:01
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
19
LZ文中到处都是在撞墙,不会是在练铁头功吧
2010-2-4 17:20
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
唉,社会黑暗啊,到处碰壁,这铁头我一定会炼就成功的
2010-2-4 17:44
0
雪    币: 401
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
先运行一下,用户名输入”xiilin”,序列号输入”1234567”,点击Test,窗口刷的一下不见了……
用peid查一下壳吧,ASPack 2.001 -> Alexey Solodovnikov,直接拿出AspackDie脱掉,再查,MASM32 / TASM32,不过文件大了很多……36KB了,呵呵,运行一下,没问题,那就OD载入吧。
先Ctrl+N查看一下输入表,看到了熟悉的GetDlgItemTextA,哈哈,bp GetDlgItemTextA下断点,F9运行起来,输入用户名”xiilin”和序列号”1234567”,点Test,断下来了,本来想Alt+F9返回用户的领空却失败了……不知跳到哪儿去了……
汗,那换个方法吧,Alt+M打开内存窗口,对用户程序的.text区段下一个内存访问断点,然后F9让程序跑起来,断在了004010FA这里,这里就是我们要找的地方了,看一看:
004010E3  |.  68 FF000000   push    0FF
004010E8  |.  68 54304000   push    00403054
004010ED  |.  68 E9030000   push    3E9
004010F2  |.  FF75 08       push    dword ptr [ebp+8]
004010F5  |.  E8 18010000   call    <jmp.&user32.GetDlgItemTextA>            ;获取用户名
004010FA  |.  0BC0          or      eax, eax
004010FC  |.  75 16         jnz     short 00401114                        ;用户名不为空就跳
004010FE  |.  68 00304000   push    00403000
00401103  |.  68 EA030000   push    3EA
00401108  |.  FF75 08       push    dword ptr [ebp+8]
0040110B  |.  E8 1A010000   call    <jmp.&user32.SetDlgItemTextA>        ;提示输入用户名,这里有个小bug,第二个参数应该是3E9而不是3EA
00401110  |.  C9            leave                                                      ;可以试一下,如果你不输入用户名,那么提示将会出现在序列号输入框里 :-)
00401111  |.  C2 1000       retn    10
00401114  |>  68 FF000000   push    0FF
00401119  |.  68 58304000   push    00403058
0040111E  |.  68 EA030000   push    3EA
00401123  |.  FF75 08       push    dword ptr [ebp+8]
00401126  |.  E8 E7000000   call    <jmp.&user32.GetDlgItemTextA>        ;获取序列号
0040112B  |.  0BC0          or      eax, eax
0040112D  |.  75 16         jnz     short 00401145                        ;序列号不为空则跳
0040112F  |.  68 11304000   push    00403011
00401134  |.  68 EA030000   push    3EA
00401139  |.  FF75 08       push    dword ptr [ebp+8]
0040113C  |.  E8 E9000000   call    <jmp.&user32.SetDlgItemTextA>        ;提示输入序列号
00401141  |.  C9            leave
00401142  |.  C2 1000       retn    10
00401145  |>  68 54304000   push    00403054
0040114A  |.  68 48304000   push    00403048
0040114F  |.  E8 A0000000   call    <jmp.&kernel32.lstrcatA>                ;用户名前面加上"pediy"字符串
00401154  |.  68 58304000   push    00403058
00401159  |.  68 48304000   push    00403048
0040115E  |.  E8 97000000   call    <jmp.&kernel32.lstrcmpA>                ;在这里进行比较
00401163  |.  0BC0          or      eax, eax
00401165  |.  75 1F         jnz     short 00401186                        ;验证失败,跳走
00401167  |.  6A 00         push    0
00401169  |.  68 2B304000   push    0040302B
0040116E  |.  68 3A304000   push    0040303A
00401173  |.  6A 00         push    0
00401175  |.  E8 A4000000   call    <jmp.&user32.MessageBoxA>                ;成功
0040117A  |.  6A 00         push    0
0040117C  |.  FF75 08       push    dword ptr [ebp+8]
0040117F  |.  E8 88000000   call    <jmp.&user32.EndDialog>
00401184  |.  EB 59         jmp     short 004011DF
00401186  |>  6A 00         push    0
00401188  |.  FF75 08       push    dword ptr [ebp+8]
0040118B  |.  E8 7C000000   call    <jmp.&user32.EndDialog>                ;失败
00401190  |.  EB 4D         jmp     short 004011DF

如果爆破那就很简单了,将00401165处的jnz改成nop,程序就跳不走了,那么试着追一下注册码吧。

本来我还觉得很简单的,但是真仔细一想,我就蒙了,仔细看一下,00403048这个地址存放的是字符串'pediy'和一个代表结束的0,00403054存放我们输入的用户名,00403058存放我们输入的序列号,那么万一我们输入的用户名不止四个字节呢?例如我输入了xiilin,那么00403058和00403059两个字节就存放了‘i’和‘n’,然后再读取我们的密码,这两个字符就被覆盖掉了,画一下现在数据在内存中的布局吧:

00403044  6F 64 21 00 70 65 64 69 79 00 00 00 00 00 40 00     od!.pediy.....@.
00403054  78 69 69 6c 31 32 33 34 35 36 37 00 00 00 00 00      xiil1234567.....
00403064  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................

当我们执行到0040114F这一句的lstrcatA的时候,事实上是将xiil1234567这个字符串0040304D这个地址之后,然后再最后添加一个0作为结束标志,那么内存中就变成了这样:

00403044  6F 64 21 00 70 65 64 69 79 78 69 69 6C 31 32 33     od!.pediyxiil123
00403054  34 35 36 37 00 32 33 34 35 36 37 00 00 00 00 00      4567.234567.....
00403064  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................

也就是说在执行lstrcmpA之前,真正的注册码就已经变成了pediyxiil1234567,但是如果我们输入pediyxiil1234567呢?注册码就又变了……因为我们输入的注册码也参加了运算——在计算真正的注册码的时候需要使用我们输入的注册码,那么换一句话来说的话也就是我们永远不可能输入正确的注册码!!当然在某种情况下这样说是不准确的,例如我们的用户名不超过三个字节,那么我们输入的注册码变不参与运算了,那就简单了,例如用户名输入1,那么注册码就是pediy1,用户名输入123,注册码就是pediy123,用户名一旦大于三个字节,那么我们就得不到正确的注册码了……

看看源代码吧,作者在inc文件中是这样写的:

         .data
;……
serial              db    'pediy'

         .data?

hInstance      dd     ?
id                   dd     ?
code              dd     ?

这里就是越界的根源了,大概作者也没想到会出现这种诡异的情况吧?修改一下:
            .data
;……
serial              db    'pediy',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0           ;添加了21个0

                   .data?

hInstance      dd     ?
id                   db     21 dup(?)
code              dd     ?

这样再编译一下的话,用户名就可以达到20个字节了,试一下,用户名输入xiilin,序列号输入pediyxiilin,验证成功。

顺便总结一下遇到的问题,希望路过的高人给能解答一下:
1、程序停在GetDlgItemTextA的断点处后,用Alt+F9为什么回不到程序的领空了?一定要给.text区段下访问断点才行么?还有什么办法快速回到程序的领空?
2、为什么有些call必须F7跟进去,如果用F8跟过去的话,程序直接就跑丢了……我也不知道跑到哪儿去了,反正肯定不是正常情况时的下一行,例如本例中0040114F处的lstrcatA和下一个lstrcmpA,难道必须每一个call都F7跟进去么?还有什么别的办法可以跳过去这些call而且程序跟不丢?这些call为什么会这样?

-----------------------------------------------------------------------------------------------------------------

我只是初学,如果你发现以上分析有什么不对的地方的话,希望能够指出,谢谢!
2010-2-4 19:41
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
看不懂,想学就是不知道从哪里入手
2010-2-4 19:50
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
感谢21楼xiilin的分析
写CM时确实没注意到0作为结束标志
  真的疏忽了
我测试时输的ID都小于3位
马上改过来
2010-2-4 22:28
0
雪    币: 474
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
     
不错啊
用汇编写CM
2010-2-4 22:57
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
近千kx?
厉害,哪个?
2010-2-6 09:19
0
游客
登录 | 注册 方可回帖
返回
//