找了个C语言100列 用来练习OD还原C语言代码 至于C+的 以后也会写

我们先来看第一个程序,我们先分析Debug的 Debug为了方便调试,代码都是一对一的翻译 没做什么优化,还原起来比较好上手,

先用OD载入,我们看到一个GetCommandLineA 我们知道 C语言真正的入口并不是main 而在main之前 会调用GetCommandLineA ,也就是说,我们往下面翻一下 可能会找到main函数,我们往下翻一下

这段代码很可疑,可能传递了3个参数,前面的ecx edx也可能是参数,所以我说可能传递了3个, 然后 call下面 add esp,0xc 表示这个函数是外平栈,那么ecx edx应该不是参数,这个call很可能是main 我们进去看看 是个jmp 再跟过去 打个断点

看到如下的代码:

我鼠标选中的(紫色背景)的代码 是debug版本初始化栈用的,先不管他,看箭头处 这里有个call push进去的参数是”\n” 我们看看这个call是什么,选中这行 按回车键跟过去

看这代码 应该是C语言的printf函数没错了,我们加个标签,这样再调用这个函数的时候就能看出来是他了,我们选中这行代码的段首 然后 右键 –标签 或者按快捷键 : 在弹出来的对话框中输入 printf 如下图

这样 以后调用printf的地方就会显示出来了,看下面的效果

OK ~

我们看看Call的下面的代码

代码有点多,先不急,我们先简单的浏览下 我们知道 ebp+4是函数返回地址 ebp+8 +c ….是函数的参数,而ebp-4 -8 ……是函数的局部变量,简单的看一下,这一段代码里面 到retn之前有3个ebp- 也就是有3个参数咯~ 我们来简单规定下 ebp-4 我们叫他i -8 叫j -c叫k

00401035 |. C745 FC 01000>mov dword ptr ss:[ebp-0x4],0x1

0040103C |. EB 09 jmp short Test1_Dd.00401047

0040103E |> 8B45 FC /mov eax,dword ptr ss:[ebp-0x4]

00401041 |. 83C0 01 |add eax,0x1

00401044 |. 8945 FC |mov dword ptr ss:[ebp-0x4],eax ; kernel32.BaseThreadInitThunk

00401047 |> 837D FC 05 cmp dword ptr ss:[ebp-0x4],0x5

0040104B  |. /7D 67         |jge short Test1_Dd.004010B4

我们先看下这一段,先给i赋值1 然后立马就跳了,跳到和5比较的地方了,然后判断 如果大于5 又跳了,我们看看他跳过去的地方的代码

004010B4 |> \33C0 xor eax,eax ; kernel32.BaseThreadInitThunk

004010B6 |. 5F pop edi ; kernel32.7578336A

004010B7 |. 5E pop esi ; kernel32.7578336A

004010B8 |. 5B pop ebx ; kernel32.7578336A

004010B9 |. 83C4 4C add esp,0x4C

也就是说 大于5 就结束了 如果小于5的话 就执行

0040104D |. C745 F8 01000>|mov dword ptr ss:[ebp-0x8],0x1

00401054 |. EB 09 |jmp short Test1_Dd.0040105F

00401056 |> 8B4D F8 |/mov ecx,dword ptr ss:[ebp-0x8] ; kernel32.7578336A

00401059 |. 83C1 01 ||add ecx,0x1

0040105C |. 894D F8 ||mov dword ptr ss:[ebp-0x8],ecx

0040105F |> 837D F8 05 | cmp dword ptr ss:[ebp-0x8],0x5

00401063 |. /7D 4D ||jge short Test1_Dd.004010B2

也就说 如果小于5的话 就执行j=1 然后判断j是不是大于5 如果大于5的话 就跳转 看看跳到哪里去了

004010B2  |>^\EB 8A         \jmp short Test1_Dd.0040103E

调到一个jmp 我们再看看jmp跳过去的地方的代码

0040103E |> /8B45 FC /mov eax,dword ptr ss:[ebp-0x4]

00401041 |. |83C0 01 |add eax,0x1

00401044 |. |8945 FC |mov dword ptr ss:[ebp-0x4],eax ; kernel32.BaseThreadInitThunk

00401047 |> |837D FC 05 cmp dword ptr ss:[ebp-0x4],0x5

0040104B |. |7D 67 |jge short Test1_Dd.004010B4

是不是有点眼熟,刚才判断i小于5的地方么?而且在判断之前还对i+1了

那么我们就能确定了 最起码 j外面有个for循环 代码应该是这样

for (i=1;i<5;i++)

{

j = 1;

if(j<5)

{

}

}

我们再看看 刚刚判断j大于5的那里 如果小于5会怎么样

00401065 |. C745 F4 01000>||mov dword ptr ss:[ebp-0xC],0x1

0040106C |. EB 09 ||jmp short Test1_Dd.00401077

0040106E |> 8B55 F4 ||/mov edx,dword ptr ss:[ebp-0xC]

00401071 |. 83C2 01 |||add edx,0x1

00401074 |. 8955 F4 |||mov dword ptr ss:[ebp-0xC],edx ; Test1_Dd.

00401077 |> 837D F4 05 || cmp dword ptr ss:[ebp-0xC],0x5

0040107B |. 7D 33 |||jge short Test1_Dd.004010B0

嗯?如果j

004010B0  |>^\EB A4         |\jmp short Test1_Dd.00401056

又是一个jmp 看看跳过去的地址,我们分析分析

00401056 |> /8B4D F8 |/mov ecx,dword ptr ss:[ebp-0x8] ; kernel32.7578336A

00401059 |. |83C1 01 ||add ecx,0x1

0040105C |. |894D F8 ||mov dword ptr ss:[ebp-0x8],ecx

0040105F |> |837D F8 05 | cmp dword ptr ss:[ebp-0x8],0x5

00401063 |. |7D 4D ||jge short Test1_Dd.004010B2

这明显是比较j小于5的代码 而且是调到j+1的地方

那么 我们的更新刚才还原出来的代码了

应该是这样

for (i=1;i<5;i++)

{

for (j=1;j<5;j++)

{

k=1;

if(k<5)

{}

}

}

好,我们在看看 k如果不跳会怎么样

0040107D |. 8B45 FC |||mov eax,dword ptr ss:[ebp-0x4]

00401080 |. 3B45 F4 |||cmp eax,dword ptr ss:[ebp-0xC]

00401083 |. 74 29 |||je short Test1_Dd.004010AE

00401085 |. 8B4D FC |||mov ecx,dword ptr ss:[ebp-0x4]

00401088 |. 3B4D F8 |||cmp ecx,dword ptr ss:[ebp-0x8] ; kernel32.7578336A

0040108B |. 74 21 |||je short Test1_Dd.004010AE

0040108D |. 8B55 F8 |||mov edx,dword ptr ss:[ebp-0x8] ; kernel32.7578336A

00401090 |. 3B55 F4 |||cmp edx,dword ptr ss:[ebp-0xC]

00401093 |. 74 19 |||je short Test1_Dd.004010AE

00401095 |. 8B45 F4 |||mov eax,dword ptr ss:[ebp-0xC]

00401098 |. 50 |||push eax ; kernel32.BaseThreadInitThunk

00401099 |. 8B4D F8 |||mov ecx,dword ptr ss:[ebp-0x8] ; kernel32.7578336A

0040109C |. 51 |||push ecx

0040109D |. 8B55 FC |||mov edx,dword ptr ss:[ebp-0x4]

004010A0 |. 52 |||push edx ; Test1_Dd.

004010A1 |. 68 1C204200 |||push Test1_Dd.0042201C ; ASCII "%d,%d,%d\n"

004010A6 |. E8 55000000 |||call

004010AB |. 83C4 10 |||add esp,0x10

好吧~k如果不跳 执行的代码有点小多。。。先不管,我们看到k里面有3个跳转,跳转的目标地址都一样 我们看看跳过去会怎么样

004010AE  |>^\EB BE         ||\jmp short Test1_Dd.0040106E

跳过去又是一个jmp 难道k也是循环?我们过去看看

0040106E  |> /8B55 F4       ||/mov edx,dword ptr ss:[ebp-0xC]

00401071  |. |83C2 01       |||add edx,0x1

00401074  |. |8955 F4       |||mov dword ptr ss:[ebp-0xC],edx        ;  Test1_Dd.

00401077  |> |837D F4 05    || cmp dword ptr ss:[ebp-0xC],0x5

0040107B  |. |7D 33         |||jge short Test1_Dd.004010B0

果然,k也是循环 那么 我们目前还原出来的代码应该是这样

int i,j,k;

for(i=1;i<5;i++)

{

for(j=1;j<5;j++)

{

for(k=1;k<5;k++)

{

}

}

}

好了 接着 我们来看看k这个循环里面的代码

0040107D |. 8B45 FC |||mov eax,dword ptr ss:[ebp-0x4]

00401080 |. 3B45 F4 |||cmp eax,dword ptr ss:[ebp-0xC] ; Test1_Dd.00404270

00401083 |. 74 29 |||je short Test1_Dd.004010AE

00401085 |. 8B4D FC |||mov ecx,dword ptr ss:[ebp-0x4]

00401088 |. 3B4D F8 |||cmp ecx,dword ptr ss:[ebp-0x8] ; Test1_Dd.00422138

0040108B |. 74 21 |||je short Test1_Dd.004010AE

0040108D |. 8B55 F8 |||mov edx,dword ptr ss:[ebp-0x8] ; Test1_Dd.00422138

00401090 |. 3B55 F4 |||cmp edx,dword ptr ss:[ebp-0xC] ; Test1_Dd.00404270

00401093 |. 74 19 |||je short Test1_Dd.004010AE

00401095 |. 8B45 F4 |||mov eax,dword ptr ss:[ebp-0xC] ; Test1_Dd.00404270

00401098 |. 50 |||push eax

00401099 |. 8B4D F8 |||mov ecx,dword ptr ss:[ebp-0x8] ; Test1_Dd.00422138

0040109C |. 51 |||push ecx

0040109D |. 8B55 FC |||mov edx,dword ptr ss:[ebp-0x4]

004010A0 |. 52 |||push edx

004010A1 |. 68 1C204200 |||push Test1_Dd.0042201C ; ASCII "%d,%d,%d\n"

004010A6 |. E8 55000000 |||call

004010AB |. 83C4 10 |||add esp,0x10

看到这么多代码 先不要慌,我们先 一句一句来读 ,下面的代码跟上面一样 但是加了注释

0040107D |. 8B45 FC |||mov eax,dword ptr ss:[ebp-0x4] ; 把i放到eax

00401080 |. 3B45 F4 |||cmp eax,dword ptr ss:[ebp-0xC] ; 比较i和k

00401083 |. 74 29 |||je short Test1_Dd.004010AE ; 如果相等就调到4010ae

00401085 |. 8B4D FC |||mov ecx,dword ptr ss:[ebp-0x4] ; 取出i 放到ecx

00401088 |. 3B4D F8 |||cmp ecx,dword ptr ss:[ebp-0x8] ; 比较i和k

0040108B |. 74 21 |||je short Test1_Dd.004010AE ; 如果相等就跳到4010ae

0040108D |. 8B55 F8 |||mov edx,dword ptr ss:[ebp-0x8] ; 取出j

00401090 |. 3B55 F4 |||cmp edx,dword ptr ss:[ebp-0xC] ; 比较k和j

00401093 |. 74 19 |||je short Test1_Dd.004010AE ; 相等就跳转

00401095 |. 8B45 F4 |||mov eax,dword ptr ss:[ebp-0xC] ; 如果i不等于k 且i不等于j 且j不等于k就会执行这里

00401098 |. 50 |||push eax ; 上面那里是取出k 这一句把k压入栈中

00401099 |. 8B4D F8 |||mov ecx,dword ptr ss:[ebp-0x8] ; 取出j

0040109C |. 51 |||push ecx ; 入栈

0040109D |. 8B55 FC |||mov edx,dword ptr ss:[ebp-0x4] ; 取出i

004010A0 |. 52 |||push edx ; 入栈

004010A1 |. 68 1C204200 |||push Test1_Dd.0042201C ; ASCII "%d,%d,%d\n"

004010A6 |. E8 55000000 |||call ; 这里调用print函数

通过上面的注释可以得出一个结论,这里是判断如果 i j k互不相等 就输出 也就是说 能还原出如下代码

int i,j,k;

for(i=1;i<5;i++)

{

for(j=1;j<5;j++)

{

for(k=1;k<5;k++)

{

if(i != k)

{

if(i != j)

{

if(j != k)

{

printf("%d,%d,%d",i,j,k);

}

}

}

}

}

}

3个if我们可以用 && 优化一下 最终的结果如下

int i,j,k;

for(i=1;i<5;i++)

{

for(j=1;j<5;j++)

{

for(k=1;k<5;k++)

{

if(i != k && i != j && j != k)

{

printf("%d,%d,%d",i,j,k);

}

}

}

}

打赏作者

微信、支付宝扫一扫,鼓励一下作者吧~

怎么解c语言逆向编码,逆向还原C语言代码 练习1相关推荐

  1. 国际c语言混乱编码大赛,国际C语言混乱代码大赛优胜作品详解之“A clock in one line”...

    下面这段代码即为第19届 IOCCC(国际混乱C语言代码大赛)优胜作品:"A clock in one line". 1 main(_){_^448&&main(- ...

  2. 国际c语言混乱编码大赛,国际C语言混乱代码大赛代码赏析(一)【转】

    国际C语言混乱代码大赛代码赏析(一) 近段时间在看<C专家编程>,里面提到国际C语言混乱代码大赛(The International Obfuscated C Code Contest I ...

  3. c语言 文件编码转换为字符串,c语言下汉字转换(字符串改为utf-8编码)

    相信大家应该都知道,汉字经过utf-8后转码会变成一串字串,其中以/分割,如:\xE7\x98\x91............,其中每三个/(十六进制)代表一个汉字,也就是一个汉字转换为了三个字节. ...

  4. c语言异或操作不能还原,C语言异或及文件操作之疑惑

    异或,逻辑运算,运算规则为:T^F=T, T^T = F, F^F = F.并且有 a = b^c, b = a^c. 因此可以简单的利用该方法加密解密.我使用了如下的程序: #include con ...

  5. C语言 | unicode 编码的中文输出

    C语言 | unicode 编码的中文输出 1.代码 /******************************************************************** > ...

  6. exe文件如何还原c语言,逆向分析:如何一步步还原C代码

    本帖最后由 shavchen 于 2019-10-22 15:44 编辑 逆向实战 逆向CallingConvention.exe,还原为C代码,记录过程. 程序入口 main函数 通过Main函数识 ...

  7. C语言二叉树的逆向有序遍历(附完整源码)

    C语言二叉树的逆向有序遍历 C语言二叉树的逆向有序遍历完整源码(定义,实现,main函数测试) C语言二叉树的逆向有序遍历完整源码(定义,实现,main函数测试) #include <iostr ...

  8. 2021年巫妖易语言-js逆向-安卓逆向hook教程

    链接:https://pan.baidu.com/s/1kdiAfXVNHgKT6BFdqzCYsw 提取码:jvw8 2021年最新巫妖易语言-js逆向-安卓逆向hook教程-10.12上课录像(这 ...

  9. 巫妖易语言+js逆向+安卓逆向

    教程介绍 2021年最新巫妖易语言+js逆向+安卓逆向hook培训教程(修复画质声音不同步不加密版),课程主要讲解的内容是易语言+js逆向+安卓逆向hook,课程是2020年11月底刚培训结束的,也是 ...

最新文章

  1. 用深层神经网络解释大脑的运作
  2. [转]开发网路游戏的延迟处理方法,广播
  3. 《C++面向对象高效编程(第2版)》——3.13 采用语义
  4. 看了这几幅图,感觉自己物理白学了!
  5. ansible解决python版本依赖
  6. ngx_pagespeed 的魔力
  7. JavaSE Collections类 , Iterator迭代器 , 增强for循环
  8. TortoiseSVN修改服务器地址的方法
  9. 百度人脸识别:功能开通
  10. 区块链软件公司:区块链的不可篡改贴合司法存证需求
  11. 微信公众号发布图文消息次数达到上限
  12. Python实现点击选择验证码破解
  13. 反脆弱性:为什么工作越稳定,人生越脆弱?
  14. 当我说要做大数据工程师时他们都笑我,直到三个月后……
  15. npm 安装碰到SSL问题
  16. C++刷题知识点总结2
  17. 深度学习和自然语言处理的应用
  18. 深度分析红米note9和华为nova8哪个好-红米note9和华为nova8区别
  19. 实习日志 (2021.09.13)
  20. cs224w(图机器学习)2021冬季课程学习笔记8 Colab 2

热门文章

  1. 为什么一个简单腹泻,服用了附子理中丸后,会绵延十年不愈?(转)
  2. 微信公众平台开发-消息管理-发送模板消息
  3. AEG 2A 400-280 HFRL1
  4. JavaEE_Swagger
  5. vscan Ineligible for use by VSAN
  6. 神经网络模型用于数学建模
  7. 图片切换马赛克动画效果
  8. 文华学院计算机专业考研,英语复试第1,初试375分,她从文华学院跨专业考研华中科技大学...
  9. [网络安全自学篇] 二.Chrome浏览器保留密码功能渗透解析及登录加密入门笔记
  10. 2021-10-12 Java 中 Filed.modifiers 之 java.lang.reflect.Modifier