标签:des style blog http color 使用 os strong
目录
2.1、ESP定律背后的原理之一:0x12FFC4,为什么是这个数 1
一般第一次总是比较傻的,但是我们在了解好逆向需要具备哪些(指令懂,君子善假于物也,这句话我经常用哈,当时写作文和说话中),就比较有想法思路了,凡是要有准备嘛。
就好比打游戏,自己操作好,打的才得心应手,打的妙。一般把第一次叫做试探。如第一次打某个BOSS,一般不看攻略或官方介绍,你总要多次尝试,(如果性子不好,急了可以放手下次从开头继续打)。这样熟悉了之后,就容易了。还有更感兴趣,可以多次刷,并掌握技巧,打的BOSS无法还手,一直悬空打那个爽啊。一个币打通游戏机社拳皇,久了被发现结果老板调了难度。
一般东西都是人做的,使用火影里鼬的话,没有不破的。凡是怕——多次试探而熟生巧。
所以第一次记录一下,主要是怎么在OllyDbg用知识,当时玩得不是很好,欢迎拍砖指导。
PEiD未发现什么,一般编译后都会显示什么的吧。入口地址=入口点+映像基址=0024D86F+00400000=0064D86F。
可见各个模块很清晰,不像经过加工的样子。
看资源,资源可见,很好啊,初始是注册的。
OllyDbg载入后第一条语句是0064D86F > $ E8 72DD0000 call 0065B5E6,见入口OEP特征
F9运行,可以看到句柄等动态分配的,看到小对话框,是未注册信息,回到OD主界面,按[Alt+M],可以查看窗口信息,如图下2图。
其实资源来自:
逆向查找目标有时是很辛苦的,有时并不是说失败成功的弹窗前一句就是关键。所以要善假于物,利用各种有利工具及其功能,之后多次熟生巧。
个人觉得逆向之破,核心就是耐心地搜索和断点来捡关键的分析。
下什么断,这里就是下简单的断,其他暂时用不到啊。
对话框一个Static控件有Unrigistered字样,肯定会调用某API的如SetWindowText(SetDlgItemText也会调它,见下图)。在这个API下断,运行,第一次断下看到如下图,并且是UNICODE版的SetWindowTextW。
说明:断点都是打在USER32模块,是因为API SetWindowTextA/W就是这个dll导出的。而这个是系统的,最安全,不管怎么调用这个函数(如导入表没SetWindowTextA/W可能是用了LoadLibary和GetProcAddress,或者自己实现的类似的功能;类似于加壳过的,就要看最后附加的文章去脱壳,然后再从这里继续;即数学方法之一——化归,不管奥数奥物理或者难题简单题都会有这类问题归一)总规会走这条路的。
可以通过下面步骤找到下断位置,查找模块中的名字(在程序领空找也行,因为前面我们看到模块导入了或者选择已加载模块USER32找)->直接打字搜索SetWindowText开头的名字->双击进入反汇编界面,设置断点。
直到看到右下角堆栈窗口显示的第二个参数Text直接为This is unregistered…,(不是This is a registered copy…难道初始加载资源设置上面那个注册的不是SetWindowTextW搞的吗)。
_In_ HWND hWnd,
_In_opt_ LPCTSTR lpString
);
User32.dll里的。
还有就是在这个断点(光标要在这行)按[Shift+F2]设置条件断点(只有满足条件才断点)。下个条件断点表达式(如上图):
UNICODE [[ESP+8]] == "Th"
或者有这个cmdBar插件,一开始就在这里下条件断点,[Alt+B]断点视窗就多了一个断点,若存在而Disable就启用。
(格式:bp address, string)
bp SetWindowTextW, UNICODE [[ESP+8]] == "Th"
举例:BOOL WINAPI SetWindowText(_In_ HWND hWnd, _In_opt_ LPCTSTR lpString);
所以调用SetWindowTextW会把两个参数从右向左(WINAPI的调用约定,其实就是stdcall,是因为#define WINAPI __stdcall。其他调用还有__cdecl,__fastcall,__thiscall等,详细请网络搜索)压栈push,ESP减4。
断到此过程前开头,ESP上存放的是返回后的下一条语句地址004C3B8C。
下面截图感受下,调用时相对ESP地址上的值情况:
直到出现或一步断下后,[Alt+K]查看堆栈或者右下角堆栈窗口。在保护模式下,栈顶是这个子过程的下一个地址。右键可以选择回去。我们可以看到如下:
条件断点触发了,这里我把有用信息框出来了,比照一下。
【解释】ESP+8的值是0012E1F0,其实也是一个地址;
这个地址所指向的内存,存放的内容是00E2F8D0,其实也是一个地址;
在堆栈窗口-右键黄色那行选择数据窗口中跟随,就可在左边那个窗口看到这个地址开始内存里的值了,由于是UNICODE字符串,所以要选好显示方式,不然OllyDbg可能想显示乱码。
【注注】此比较是把这个字符串转为ASCII,再和你给的"Th"常量字符串比较的,不匹配长度,类似正则表达式^xxx.*这里xxx就是你的菜。
从图上, USER32 里的 SetWindowTextW映射到本程序的进程地址空间后的样子(地址比较大吧)。我们需要回到程序领空(地址小,就是win32应用映射后的text),执行到用户代码[Alt+F9]。
主要查找可疑代码,如判断跳转(JZ、JMP等,一般前面有比较指令等会改变标志位)等。
改变跳转条件
如何回溯,从编程人员角度想想可能的调用栈举例情况:
首先是回溯到用户程序领空,因为前一个断点都是打在系统领空的。
再就是找调用前有跳过断点call(子call,子子call,…)的判断跳转。
直接看出无关的子调用过程直接跳过,执行到返回并步过,到上级过程,再查看是否相关(系统API或封装的一般是直接跳过的子过程)。
回到进入子过程的下一个位置,就是前一步右下角堆栈的地址。这里好多API放一起可能是被封起来用的,这是一个子过程,往上看到入口地址004C3B4A就是SetDlgItemText(int cotrolId, TCHAR *pszText)这样。这里需要再往上一级调用跑。只有几步就回去了,直接步过回去,就可以。
或者[Alt+K]打开调用堆栈,记录了简单调用过程,???是未知,可能是动态调用,还没确认,如call eax等。
解释:正常用高级语言写的程序,函数在运行时都有固定位置,反汇编后就是call xxxxxxxx,静态的。但是凡是总有例外,如果程序员使用了内嵌asm、函数指针等,或者对象中的函数。
0044760F |. E8 1EC30700 call 004C3932 ; call跳转地址(过程开始地址) = call起始位置+ call后面的操作数+5(指令字节长度)= call结束位置(下一条语句起始位置)+call后面的操作数。
00447614 |. 8BC8 mov ecx, eax ; 004C3932 = 0044760F + 0007C31E + 5 = 00447614 + 0007C31E,注意:机器码E8后面所跟的32位数是little-endian格式(x86是小尾模式)的,低位在前,高位在后。
跳转主要就是改变EIP指令寄存器,可以动态跟踪一下:call执行前和步入后,查看寄存器窗口里EIP的值改变情况。由于EIP不能直接改变,所以可以借助无条件跳转JMP来跳到任意位置,以此间接改变EIP。
Opcode CALL
CPU: 8086+
Type of Instruction: User
Instruction: CALL procadr
Physical form:
| Near call - withing the same segment 段内调用
| Far call - call to another segment 段间调用
E8 cw CALL rel16 ; Near call, operand specifies relative displacement to next instruction 操作数指定了下一条指令的相对位移
E8 cd CALL rel32 ; Near call, operand specifies relative displacement to next instruction
FF /2 CALL r/m16 ; Near call, absolute address
FF /2 CALL r/m32 ; Near call, absolute address
9A cd CALL ptr16:16 ; Far call, absolute addres
9A cp CALL ptr16:32 ; Far call, absolute address
FF /3 CALL m16:16 ; Far call, absolute address
FF /3 CALL m16:32 ; Far call, absolute address
[Alt+K] 调用堆栈界面
? 双击【过程(Procedure/arguments)】栏的项目或某行右键菜单选择【跟随过程(follow) /(show procedure)】,则会进入CPU界面定位于反汇编窗口内的对应的方法开头;
? 双击【调用从(Called from)】栏的项目或某行右键菜单选择【跟随Caller(follow) / (show call)】,则会进入CPU界面定位于反汇编窗口内的相应的call语句地址。
? 第一行【Stack】列式当前断点ESP值,指向的内容是过程USER32.SetWindowTextW返回后的地址,即call语句的下一句地址,显示在【数据】一列。
? 其他行是上一级call历史记录,再上一级的call,可以看出从入口第一个ESP(一般为0x12FFC4,详见入口ESP)到当前断点的所有过程都记录下来了。
? 这里是无法记录每级别同等层次的其他call过程,即曾调用过的所有非直系的call,因为已经出栈了,但是可以使用跟踪来记录所有。
回去后看到,文本已经变成未注册的了,前面有好多判断跳转,貌似都不是好跳转。
在前一个调用004C3B4A设置断点,其他的删除,先设距离大点,或者也可再设置一个,这句(Local.22是本地变量,OD命名见下图-栈图,即EBP - 22. * 4 = EBP - 88. = EBP - 58):
CPU Disasm
地址 十六进制数据 指令 注释
004475FC |. 8D4D A8 LEA ECX,[LOCAL.22]
重新运行[Ctrl+F2]。再按[F9]到断点处,鼠标点击工具栏的W图标按钮(Alt+W)打开窗口视图,如下图:
如果继续运行就变成未注册。
我们会发现这个过程,其实只是操作界面的过程。
其实,通过点击前面各个跳转指令看跳转位置,发现没有跳过加载资源839的那块语句和SetWindowTextW的。
我们猜测注册后打开时弹窗不该出现,但是,主界面Help->About菜单或工具栏?按钮也会弹出此窗口,且是同一段代码,可以通过断点或者MFC编程规则查找OnCommand的处理。所以还是某处判断并调用此段代码。还有一点,前面推测C++封装代码,还有OD自助推测CDialog可推知是MFC写的,其他详细见符号分析。
双击USER32.CreateDialogIndirectParamW调用来自进入call位置,在上面跟随标签。
这个窗口制造返回前会调用,参数DialogFunc,如下图
前一个断下后在sr32.AfxDlgProc(HWND__ *,uint,uint,long)(推测 hWnd,Msg,wParam,lParam)或者关心的跳转CALL DWORD PTR DS:[EDX+174]下断,可以看到对参数2进行了特别处理,意思是消息为WM_INITDIALOG= $0110;时不跳转而调用对象方法。
观察右下角堆栈窗口的第二个参数,第一个消息是 WM_SETFONT= $0030;之后就是WM_INITDIALOG= $0110;了。此时CALL DWORD PTR DS:[EDX+174]是对象方法的调用,会进入我们前面调用SetWindowtextW的方法里。
以上,通过IDA可以方便查看WM_INITDIALOG的消息处理,没有能跳过的跳转,故这个调用舍去,继续分析上一级调用:
以另外一个地方,显示受限功能弹窗的为例。
85E=2142. Only up to 5 files can be replaced this session in the Unregistered Version.$0ADo you want to see the Ordering Information?
回到OllyDbg按下[F12]或工具栏的暂停按钮,状态栏最右边就会出现暂停字样。
再用[Alt+K]打开前面提到的调用堆栈,因为显示的比CPU界面(主界面)右下角堆栈窗口(不反对放大,然后往下回溯调用)简单,容易看。没有符号详细见符号分析。工具利用起来事半功倍。
点击sr32.AfxMessageBox(uint,uint,uint)回到哪里调用它的。
前面跳转就是控制显示弹窗,在这下断,重新测试替换功能,手动设置标志位寄存器的Z标识或者直接改为无条件跳转JMP。
猜想结果:如果8个文件有未成功,需要查看弹窗判断和替换的循环操作是否各有判断。
即可能类似这样:
void DoReplace()
{
BOOL bUnregistered = CheckUnregistered();
If(bUnregistered)
{
UnregisteredUserReplaceHandler(BOOL bFirstReplace, BOOL bShowBackupTip){
If(count > 5)
{
ShowLimitedTip(){
sr32.AfxMessageBox(uint,uint,uint);
};
}
};
If(count > 5)
{
count = 5;
}
}
}
发现没有弹窗但是还只是替换了5个。查找和5比较或间接比较的地方。
个人觉得经验就是:把别人的"写"成自己的(积累的快),自己的再不断探探究究(看自己能力实践)。
靠时间来谈论经验有几年谁都能啊。这样看什么帖子了就容易多了,不会有哪里没讲的而不明白,加速。时候成熟了,设计一款产品。
OllyDbg可以通过一定办法加载IDA的map文件,导入符号。
如下图,OllyDbg一加载的场景截图
当用IDA打开后,会在后台不断解析符号。
网络上有人的总结:
Microsoft Visual C++ 6.0
00496EB8 >/$ 55 PUSH EBP ; (初始 cpu 选择)
00496EB9 |. 8BEC MOV EBP,ESP
00496EBB |. 6A FF PUSH -1
00496EBD |. 68 40375600 PUSH Screensh.00563740
00496EC2 |. 68 8CC74900 PUSH Screensh.0049C78C ; SE 处理程序安装
00496EC7 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00496ECD |. 50 PUSH EAX
00496ECE |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
00496ED5 |. 83EC 58 SUB ESP,58
Microsoft Visual Basic 5.0 / 6.0
00401166 - FF25 6C104000 JMP DWORD PTR DS:[<&MSVBVM60.#100>] ; MSVBVM60.ThunRTMain
0040116C > 68 147C4000 PUSH PACKME.00407C14
00401171 E8 F0FFFFFF CALL <JMP.&MSVBVM60.#100>
00401176 0000 ADD BYTE PTR DS:[EAX],AL
00401178 0000 ADD BYTE PTR DS:[EAX],AL
0040117A 0000 ADD BYTE PTR DS:[EAX],AL
0040117C 3000 XOR BYTE PTR DS:[EAX],AL
或省略第一行的JMP
00401FBC > 68 D0D44000 push dumped_.0040D4D0
00401FC1 E8 EEFFFFFF call <jmp.&msvbvm60.ThunRTMain>
00401FC6 0000 add byte ptr ds:[eax],al
00401FC8 0000 add byte ptr ds:[eax],al
00401FCA 0000 add byte ptr ds:[eax],al
00401FCC 3000 xor byte ptr ds:[eax],al
00401FCE 0000 add byte ptr ds:[eax],al
BC++
0040163C > $ /EB 10 JMP SHORT BCLOCK.0040164E
0040163E |66 DB 66 ; CHAR ‘f‘
0040163F |62 DB 62 ; CHAR ‘b‘
00401640 |3A DB 3A ; CHAR ‘:‘
00401641 |43 DB 43 ; CHAR ‘C‘
00401642 |2B DB 2B ; CHAR ‘+‘
00401643 |2B DB 2B ; CHAR ‘+‘
00401644 |48 DB 48 ; CHAR ‘H‘
00401645 |4F DB 4F ; CHAR ‘O‘
00401646 |4F DB 4F ; CHAR ‘O‘
00401647 |4B DB 4B ; CHAR ‘K‘
00401648 |90 NOP
00401649 |E9 DB E9
0040164A . |98E04E00 DD OFFSET BCLOCK.___CPPdebugHook
0040164E > \A1 8BE04E00 MOV EAX,DWORD PTR DS:[4EE08B]
00401653 . C1E0 02 SHL EAX,2
00401656 . A3 8FE04E00 MOV DWORD PTR DS:[4EE08F],EAX
0040165B . 52 PUSH EDX
0040165C . 6A 00 PUSH 0 ; /pModule = NULL
0040165E . E8 DFBC0E00 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401663 . 8BD0 MOV EDX,EAX
Borland Delphi 6.0 - 7.0
00509CB0 > $ 55 PUSH EBP
00509CB1 . 8BEC MOV EBP,ESP
00509CB3 . 83C4 EC ADD ESP,-14
00509CB6 . 53 PUSH EBX
00509CB7 . 56 PUSH ESI
00509CB8 . 57 PUSH EDI
00509CB9 . 33C0 XOR EAX,EAX
00509CBB . 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
00509CBE . B8 20975000 MOV EAX,unpack.00509720
00509CC3 . E8 84CCEFFF CALL unpack.0040694C
易语言入口
00401000 > E8 06000000 call dump_.0040100B
00401005 50 push eax
00401006 E8 BB010000 call <jmp.&KERNEL32.ExitProcess>
0040100B 55 push ebp
0040100C 8BEC mov ebp,esp
0040100E 81C4 F0FEFFFF add esp,-110
00401014 E9 83000000 jmp dump_.0040109C
00401019 6B72 6E 6C imul esi,dword ptr ds:[edx+6E],6C
0040101D 6E outs dx,byte ptr es:[edi]
也可能是这样的入口
Microsoft Visual C++ 6.0 [Overlay] E语言
00403831 >/$ 55 PUSH EBP
00403832 |. 8BEC MOV EBP,ESP
00403834 |. 6A FF PUSH -1
00403836 |. 68 F0624000 PUSH Nisy521.004062F0
0040383B |. 68 A44C4000 PUSH Nisy521.00404CA4 ; SE 处理程序安装
00403840 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00403846 |. 50 PUSH EAX
00403847 |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
MASM32 / TASM32入口
00401258 >/$ 6A 00 push 0 ; /pModule = NULL
0040125A |. E8 47000000 call <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
0040125F |. A3 00304000 mov dword ptr ds:[403000],eax
00401264 |. 6A 00 push 0 ; /lParam = NULL
00401266 |. 68 DF104000 push dump.004010DF ; |DlgProc = dump.004010DF
0040126B |. 6A 00 push 0 ; |hOwner = NULL
0040126D |. 6A 65 push 65 ; |pTemplate = 65
0040126F |. FF35 00304000 push dword ptr ds:[403000] ; |hInst = NULL
00401275 |. E8 56000000 call <jmp.&user32.DialogBoxParamA> ; \DialogBoxParamA
004A2ADC > $ E8 B6A40000 call 记事本.004ACF97
004A2AE1 .^ E9 16FEFFFF jmp 记事本.004A28FC
004A2AE6 CC int3
004A2AE7 CC int3
004A2AE8 CC int3
004A2AE9 CC int3
004A2AEA CC int3
004A2AEB CC int3
004A2AEC CC int3
004A2AED CC int3
004A2AEE CC int3
004A2AEF CC int3
004A2AF0 /$ 8B4C24 04 mov ecx,dword ptr ss:[esp+4]
004A2AF4 |. F7C1 03000000 test ecx,3
004A2AFA |. 74 24 je short 记事本.004A2B20
004A2AFC |> 8A01 /mov al,byte ptr ds:[ecx]
004A2AFE |. 83C1 01 |add ecx,1
标 题: 【原创】ESP定律背后的原理之一:0x12FFC4,为什么是这个数
作 者: tnttools
时 间: 2008-02-05,16:13:41
链 接: http://bbs.pediy.com/showthread.php?t=59352
ESP定律背后的原理之一:0x12FFC4
ESP定律:如果压缩壳执行前后的堆栈会维持平衡,在12FFC0上下读写断点,会中断在OEP的第一条指令push ebp上。那么各位有没有探究过ESP的尾数值为什么不是0xFFFC,而是0x0FFC4?这是由windows源代码的实现所确定的。
Windows创建进程的函数链为kernel32.dll!_CreateProcessInternalW -> … -> kernel32.dll!_BaseProcessStartThunk() -> kernel32.dll!_BaseProcessStart() -> EP
在进入_BaseProcessStartThunk()时,堆栈的状态确实为
+ 0012FFFC 00000000 <- ESP
---------------------------------------------------------<code>
_BaseProcessStartThunk@8 proc near
xor ebp, ebp
push eax
push 0
jmp _BaseProcessStart@4 ; BaseProcessStart(x)
_BaseProcessStartThunk@8 endp
----------------------------------------------------------</code>
在执行完_BaseProcessStartThunk时,堆栈的状态为
+ 0012FFFC 00000000
+ 0012FFF8 EAX
+ 0012FFF4 0x00000000 <- ESP
---------------------------------------------------------<code>
_BaseProcessStart proc
push 0Ch
push offset dword_7C816FE0
call __SEH_prolog
and [ebp+ms_exc.disabled], 0
push 4
lea eax, [ebp+8]
push eax
push 9
push 0FFFFFFFEh
call ds:__imp__NtSetInformationThread@16 ; NtSetInformationThread(x,x,x,x)
call dword ptr [ebp+8]
push eax ; dwExitCode
call _ExitThread@4
nop
nop
nop
---------------------------------------------------------</code>
在执行完BaseProcessStart()后,堆栈的状态为
+ 0012FFFC 0x00000000
+ 0012FFF8 OldEAX -2-> EntryPoint By NtSetInformationThread()
+ 0012FFF4 reserved, inited to 0x00000000
+ 0012FFF0 OldEBP(0x00000000) <-p- NowEBP
+ 0012FFEC TryLevel, inited to 0xFFFFFFFF
+ 0012FFE8 ScopeTable
+ 0012FFE4 __except_handler3 in kernel32.dll
+ 0012FFE0 0xFFFFFFFF <-p- fs:00h
+ 0012FFDC ExceptionInfo, Parameter of UnhandledExceptionFilter()
+ 0012FFD8 OldESP(0x0012FFC8)
+ 0012FFD4 ExceptionCode, Parameter of kernel32.dll!ExitProcess
+ 0012FFD0 EBX(pPEB)
+ 0012FFCC ESI
+ 0012FFC8 EDI <-p- OldESP
+ 0012FFC4 retaddr in kernel32.dll!_BaseProcessStartThunk
<-p- NowESP
附:
DWORD SizeOfStackReserve; // 0x48-4b
DWORD SizeOfStackCommit; // 0x4c-4f
DWORD SizeOfHeapReserve; // 0x50-53
DWORD SizeOfHeapCommit; // 0x54-57
这是IOH中的四个域。
Reserved保留的, Committed提交的是两种类型的虚拟内存。
Reserved指这段内存已有用途,不能再被分配;Committed提交的内存指的是已经与物理内存有映射的虚拟内存段(当然也可以被移到硬盘上的缓存文件pagefile.sys中)。因为Stack, Heap这两种类型的内存段都有随着程序的运行尺寸不断增大的特性,所以一开始不必占用太多宝贵的物理内存,当它们用完了,会引发内存异常,windows内存管理器就又为程序分配一部分。
SizeOfStackReserve 程序开始时保留用作堆栈空间的内存段的大小
SizeOfStackCommit 程序开始时在保留的堆栈内存段中与物理内存映射的提交的内存段的大小
SizeOfHeapReserve 程序开始时保留用作堆空间的内存段的大小
SizeOfHeapCommit 程序开始时在保留的堆内存段中与物理内存映射的提交的内存段的大小
那么各位有没有想过为什么在进入任何一个程序时,ESP的值都是0x12FFC4。
脱壳入门初级教学http://bbs.pediy.com/showthread.php?t=20366
注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由操作系统决定,将SizeOfStackCOmmit改大ESP就会变,这是因为操作系统从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。
标 题: 脱壳基础知识入门及FAQ
作 者: kanxue
时 间: 2006-01-14 17:20
链 接: http://bbs.pediy.com/showthread.php?t=20366
非课文,摘自网络。
君子曰:学不可以已。
青,取之于蓝而青于蓝;冰,水为之而寒于水。木直中绳,輮(左应为"车",原字已废除)以为轮,其曲中规。虽有槁暴,不复挺者,輮使之然也。故木受绳则直,金就砺则利,君子博学而日参省乎己,则知明而行无过矣。
故不登高山,不知天之高也;不临深溪,不知地之厚也;不闻先王之遗言,不知学问之大也。干、越、夷、貉之子,生而同声,长而异俗,教使之然也。诗曰:"嗟尔君子,无恒安息。靖共尔位,好是正直。神之听之,介尔景福。"神莫大于化道,福莫长于无祸。
吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。登高而招,臂非加长也,而见者远;顺风而呼,声非加疾也,而闻者彰。假舆马者,非利足也,而致千里;假舟楫者,非能水也,而绝江河。君子生非异也,善假于物也。
南方有鸟焉,名曰蒙鸠,以羽为巢,而编之以发,系之苇苕,风至苕折,卵破子死。巢非不完也,所系者然也。西方有木焉,名曰射干,茎长四寸,生于高山之上,而临百仞之渊,木茎非能长也,所立者然也。蓬生麻中,不扶而直;白沙在涅,与之俱黑。兰槐之根是为芷,其渐之滫,君子不近,庶人不服。其质非不美也,所渐者然也。故君子居必择乡,游必就士,所以防邪辟而近中正也。
物类之起,必有所始。荣辱之来,必象其德。肉腐出虫,鱼枯生蠹。怠慢忘身,祸灾乃作。强自取柱,柔自取束。邪秽在身,怨之所构。施薪若一,火就燥也,平地若一,水就湿也。草木畴生,禽兽群焉,物各从其类也。是故质的张,而弓矢至焉;林木茂,而斧斤至焉;树成荫,而众鸟息焉。醯酸,而蚋聚焉。故言有招祸也,行有招辱也,君子慎其所立乎!
积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。
是故无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。行衢道者不至,事两君者不容。目不能两视而明,耳不能两听而聪。螣蛇无足而飞,鼫鼠五技而穷。《诗》曰:"尸鸠在桑,其子七兮。淑人君子,其仪一兮。其仪一兮,心如结兮!"故君子结于一也。
昔者瓠巴鼓瑟,而流鱼出听;伯牙鼓琴,而六马仰秣。故声无小而不闻,行无隐而不形 。玉在山而草润,渊生珠而崖不枯。为善不积邪?安有不闻者乎?
学恶乎始?恶乎终?曰:其数则始乎诵经,终乎读礼;其义则始乎为士,终乎为圣人, 真积力久则入,学至乎没而后止也。故学数有终,若其义则不可须臾舍也。为之,人也;舍 之,禽兽也。故书者,政事之纪也;诗者,中声之所止也;礼者,法之大分,类之纲纪也。 故学至乎礼而止矣。夫是之谓道德之极。礼之敬文也,乐之中和也,诗书之博也,春秋之微 也,在天地之间者毕矣。 君子之学也,入乎耳,着乎心,布乎四体,形乎动静。端而言,蝡而动,一可以为法则。小人之学也,入乎耳,出乎口;口耳之间,则四寸耳,曷足以美七尺之躯哉!古之学者为己,今之学者为人。君子之学也,以美其身;小人之学也,以为禽犊。故不问而告谓之傲,问一而告二谓之囋。傲、非也,囋、非也;君子如向矣。
学莫便乎近其人。礼乐法而不说,诗书故而不切,春秋约而不速。方其人之习君子之说,则尊以遍矣,周于世矣。故曰:学莫便乎近其人。
学之经莫速乎好其人,隆礼次之。上不能好其人,下不能隆礼,安特将学杂识志,顺诗书而已耳。则末世穷年,不免为陋儒而已。将原先王,本仁义,则礼正其经纬蹊径也。若挈裘领,诎五指而顿之,顺者不可胜数也。不道礼宪,以诗书为之,譬之犹以指测河也,以戈舂黍也,以锥餐壶也,不可以得之矣。故隆礼,虽未明,法士也;不隆礼,虽察辩,散儒也。
问楛者,勿告也;告楛者,勿问也;说楛者,勿听也。有争气者,勿与辩也。故必由其道至,然后接之;非其道则避之。故礼恭,而后可与言道之方;辞顺,而后可与言道之理;色从而后可与言道之致。故未可与言而言,谓之傲;可与言而不言,谓之隐;不观气色而言,谓瞽。故君子不傲、不隐、不瞽,谨顺其身。诗曰:"匪交匪舒,天子所予。"此之谓也。
百发失一,不足谓善射;千里蹞步不至,不足谓善御;伦类不通,仁义不一,不足谓善学。学也者,固学一之也。一出焉,一入焉,涂巷之人也;其善者少,不善者多,桀纣盗跖也;全之尽之,然后学者也。
君子知夫不全不粹之不足以为美也,故诵数以贯之,思索以通之,为其人以处之,除其害者以持养之。使目非是无欲见也,使耳非是无欲闻也,使口非是无欲言也,使心非是无欲虑也。及至其致好之也,目好之五色,耳好之五声,口好之五味,心利之有天下。是故权利不能倾也,群众不能移也,天下不能荡也。生乎由是,死乎由是,夫是之谓德操。德操然后能定,能定然后能应。能定能应,夫是之谓成人。天见其明,地见其光,君子贵其全也。
这里有译文:http://baike.baidu.com/subview/17130/5060547.htm?fr=aladdin
第一次OllyDbg逆向记录(分析思路和注意点&其他文章),布布扣,bubuko.com
标签:des style blog http color 使用 os strong
原文地址:http://www.cnblogs.com/Fang3s/p/3872294.html