易语言教程_易语言源码_易语言视频教程_易语言论坛

 找回密码
 点击注册

Vip新手入门区
新手学习指南  学员作品展示 Vip课程总纲  Vip绝密课程系列

Vip相关下载区
Vip模块下载   Vip模块绑定   Vip模块例子 魔鬼插件下载  魔鬼插件例子  教程工具下载

Vip论坛服务区
教程问题提问区   模块问题提问区 技术交流区   魔鬼插件建议   忘记密码找回

VIP会员办理QQ: 8643245   
【请先加好友,然后到好友列表双击联系客服,办理VIP会员。】
【基础篇】易语言辅助入门基础教程
VIP模块办理QQ: 7189694 办理正版魔鬼作坊VIP模块 【基础篇】OD与CE入门基础教程
办理【终身VIP会员】“秒杀价” 仅需 RMB278.00元… 【基础篇】零基础绝密汇编语言入门课程 (共26课已完成)…
办理VIP详情…猛击这里查看详情 【基础篇】VIP辅助入门基础教程-新手必学 已发布10课 ……
VIP教程免费试看章节…猛击下载 【第1款】制作“辅助挂”教程目录查看(共107+16_x64下更新课已完成)…
亲爱的VIP学员,请到此写下你学习的感受与发布作品截图… 【第2款】制作“任务挂”教程目录查看(共77+1_x64下更新课已完成)…
卍解吧!不用bp send类封包断点找CALL的各种通杀思路 【第3款】驱动过保护技术课程(共38课已完成)…
【绝密教程】VIP绝密教程系列---注意:随时会更新! 【第4款】VIP邪恶二叉树辅助课程 (共31+17_x64下更新课已完成)…
【精品第13款】3D射击游戏与页游透视 智辅课程 已完成17课… 【第5款】零基础易语言按键辅助教程 (30课已完成)…
【精品第14款】变态功能辅助是如何炼成的 已完成36课… 【第6款】从零开始学习封包辅助技术教程(20课已完成) …
【精品第15款】DNF商业变态辅助的修炼之路 已完成27课… 【第7款】大杀特杀分析来源与CALL吸血鬼课程 (56课已完成)
【精品第16款】中控台多线程多开自动化商业辅助课程 已完成66课… 【第8款】完全零基础网页辅助课程(40课已完成)
【全新精品第17款】检测原理与过游戏内存检测技术课程 已发布9课… 【第9款】自动登录与操控LUA技术课程 (共46+8_x64下更新课已完成)…
【全新精品第18款】手游全自动化任务脚本辅助课程 已发布25课…… 【第10款】网页辅助封包脱机进阶课程 已完成30课…
【全新精品第19款】D3D方框骨骼透视与自瞄辅助课程进阶篇 已发布34课…… 【第11款】VC++ Lua脚本辅助课程 已完成112课…
【全新精品第20款】 X64模拟器吃鸡游戏方框透视自瞄辅助课程 发布中... 【第12款】网游脱机封包智辅课程 已完成35课…
查看: 1676|回复: 6

结构体的逆向分析(上)

[复制链接]

54

主题

98

回帖

130

积分

终身VIP会员

花钱是让你服务的,不是叫你大哥 ...

Rank: 7Rank: 7Rank: 7

魔鬼币
10632
发表于 2011-8-30 21:35:49 | 显示全部楼层 |阅读模式
分析下结构体,是为了向类过渡。
*针对C语言
问题原型:候选人得票的统计程序。设3个候选人, 每次输入一个得票的候选人的名字, 要求最后输出个候选人的得票结果。
C源码:
#include <stdio.h>
#include <string.h>

struct person
{
        char name[20];
        int count;
}leader[3] = {"Li",0, "Zhang",0, "Wang",0};

int main(void)
{
        int i, j, n;
        char leader_name[20];
        printf("enter n:"); scanf("%d", &n);
        for(i=0; i<n; i++)
        {
                scanf("%s", leader_name);
                for(j=0; j<3; j++)
                {
                        if(strcmp(leader_name, leader[j].name) == 0)
                        {
                                leader[j].count++;
                                break;
                        }
                }
        }
        for(i=0; i<3; i++)
                printf("%5s:%d\n", leader.name, leader.count);       
        return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////...
OD主程序反汇编代码(有点长,如果觉得没意思的话直接跳过看最后吧):
00401010 >|> \55            push ebp
00401011  |.  8BEC          mov ebp,esp
00401013  |.  83EC 60       sub esp,0x60
00401016  |.  53            push ebx
00401017  |.  56            push esi
00401018  |.  57            push edi
00401019  |.  8D7D A0       lea edi,[local.24]
0040101C  |.  B9 18000000   mov ecx,0x18
00401021  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC
00401026  |.  F3:AB         rep stos dword ptr es:[edi]
00401028  |.  68 30504200   push new18.00425030                      ; /format = "enter n:"
0040102D  |.  E8 1E020000   call new18.printf                        ; \printf
00401032  |.  83C4 04       add esp,0x4
00401035  |.  8D45 F4       lea eax,[local.3]
00401038  |.  50            push eax
00401039  |.  68 2C504200   push new18.0042502C                      ; /format = "%d"
0040103E  |.  E8 AD010000   call new18.scanf                         ; \scanf
00401043  |.  83C4 08       add esp,0x8
00401046  |.  C745 FC 00000>mov [local.1],0x0   //非常典型for语句的开端, i初始化为0
0040104D  |.  EB 09         jmp Xnew18.00401058
0040104F  |>  8B4D FC       /mov ecx,[local.1]
00401052  |.  83C1 01       |add ecx,0x1  //执行完for循环体后的表达式;
00401055  |.  894D FC       |mov [local.1],ecx
00401058  |>  8B55 FC        mov edx,[local.1]
0040105B  |.  3B55 F4       |cmp edx,[local.3]  //local.3 显然是局部变量n
0040105E  |.  7D 67         |jge Xnew18.004010C7
00401060  |.  8D45 E0       |lea eax,[local.8]  //获取输入字符串的指针
00401063  |.  50            |push eax        //并压入
00401064  |.  68 28504200   |push new18.00425028             ; /format = "%s" 的首地址
00401069  |.  E8 82010000   |call new18.scanf                        ; \scanf
0040106E  |.  83C4 08       |add esp,0x8
              // for(j=0; j<3; j++)
00401071  |.  C745 F8 00000>|mov [local.2],0x0
00401078  |.  EB 09         |jmp Xnew18.00401083
0040107A  |>  8B4D F8       |/mov ecx,[local.2]
0040107D  |.  83C1 01       ||add ecx,0x1
00401080  |.  894D F8       ||mov [local.2],ecx
00401083  |>  837D F8 03    | cmp [local.2],0x3
00401087  |.  7D 3C         ||jge Xnew18.004010C5 //如果变量j超过3,则代表不存在这个候选人;
// 这里是这个程序的核心部分, 判断用户输入的名字是否与在结构体数组中存在
00401089  |.  8B55 F8       ||mov edx,[local.2]  //edx存放变量j
0040108C  |.  6BD2 18       ||imul edx,edx,0x18 // j = j * 18h (18h为结构体的大小)
0040108F  |.  81C2 307A4200 ||add edx,offset new18.leader  //结构体数组的首地址+j*18h 定位结构体数组的下标的首地址,这里就是结构体数组的成员变量name
00401095  |.  52            ||push edx   //参数1 结构数组成员变量name字符串首地址
00401096  |.  8D45 E0       ||lea eax,[local.8]  //local.8 就是当前的用户输入字符串的指针
00401099  |.  50            ||push eax    //参数2 用户输入字符串首地址
0040109A  |.  E8 C1000000   ||call new18.strcmp //调用库函数strcmp,判断是否字符串完全相等
0040109F  |.  83C4 08       ||add esp,0x8  //如果字符串完全相等,则返回eax=0
004010A2  |.  85C0          ||test eax,eax  //如果eax=0, 则标志位寄存器zf 置 1
004010A4  |.  75 1D         ||jnz Xnew18.004010C3  //zf = 0 则跳转
                         // 字符串相等的处理代码
004010A6  |.  8B4D F8       ||mov ecx,[local.2]  //变量j
004010A9  |.  6BC9 18       ||imul ecx,ecx,0x18  //ecx = j + j*18h
004010AC  |.  8B91 447A4200 ||mov edx,dword ptr ds:[ecx+0x427A44] //同(add edx,offset new18.leader) 同样是定位结构体数组下标指向的首地址
004010B2  |.  83C2 01       ||add edx,0x1  //count计数+1
//leader[j].count++;
004010B5  |.  8B45 F8       ||mov eax,[local.2]
004010B8  |.  6BC0 18       ||imul eax,eax,0x18
004010BB  |.  8990 447A4200 ||mov dword ptr ds:[eax+0x427A44],edx
004010C1  |>  EB 02         |\jmp Xnew18.004010C5  //第一个jmp,跳至004010c5
                        //字符串不相等则跳到这里
004010C3  |>^ EB B5         \jmp Xnew18.0040107A   //第二个跳转,说明是字符串不相等才跳过来的,继续执行for(j=0; j<3; j++)循环;
004010C5  |>^ EB 88         jmp Xnew18.0040104F  //是从第一个jmp跳过来的,继续跳回for(i=0; i<n; i++)处;
// 开始打印输出了。。。。以下略
004010C7  |?  C745 FC 00000>mov [local.1],0x0
004010CE  |>  EB 09         /jmp Xnew18.004010D9
004010D0  |?  8B4D FC       mov ecx,[local.1]
004010D3  |?  83C1 01       add ecx,0x1
004010D6  |?  894D FC       mov [local.1],ecx
004010D9  |?  837D FC 03    cmp [local.1],0x3
004010DD  |.  7D 29         |jge Xnew18.00401108
004010DF  |?  8B55 FC       mov edx,[local.1]
004010E2  |?  6BD2 18       imul edx,edx,0x18
004010E5  |?  8B82 447A4200 mov eax,dword ptr ds:[edx+0x427A44]
004010EB  |?  50            push eax
004010EC  |?  8B4D FC       mov ecx,[local.1]
004010EF  |?  6BC9 18       imul ecx,ecx,0x18
004010F2  |?  81C1 307A4200 add ecx,offset new18.leader              ;  ASCII "Li"
004010F8  |?  51            push ecx
004010F9  |?  68 1C504200   push new18.0042501C                      ;  ASCII "%5s:%d
"
004010FE  |?  E8 4D010000   call new18.printf
00401103  |?  83C4 0C       add esp,0xC
00401106  |>^ EB C8         jmp Xnew18.004010D0
00401108  |.  33C0          xor eax,eax
0040110A  |.  5F            pop edi
0040110B  |.  5E            pop esi
0040110C  |?  5B            pop ebx
0040110D  |?  83C4 60       add esp,0x60
00401110  |.  3BEC          cmp ebp,esp
00401112  |?  E8 B9010000   call new18._chkesp
00401117  |.  8BE5          mov esp,ebp
00401119      5D            pop ebp

注释:关于结构体的逆向,我觉得主要有两个问题:
第一:结构体数据在内存中如何存放?
第一个问题,和数组类似,结构体是线性的连续存放在内存中的。
第二:如何引用(操作)结构体(数组)成员变量?
这个问题也可以理解为, 如何定位结构体数组的成员变量。

让我们来看这几行代码:
00401089  |.  8B55 F8       ||mov edx,[local.2]  //edx存放变量j
0040108C  |.  6BD2 18       ||imul edx,edx,0x18 // j = j * 18h (18h为结构体的大小)
0040108F  |.  81C2 307A4200 ||add edx,offset new18.leader  //结构体数组的首地址+j*18h+0 定位结构体数组的下标的首地址,这里就是结构体数组的成员变量name
00401095  |.  52            ||push edx   //参数1 结构数组成员变量name字符串首地址
我们定位一个结构体数组的成员变量, 首先需要知道该结构体的大小(占用的字节数) 。这里我们已经知道c源码了,所以不难发现结构体的大小为20+4=18h。
可是,当我们逆向分析一个无源码的程序时,只能通过逆向分析来抽丝剥茧的还原本来的代码。
这里很简单, imul edx,edx,0x18 这条指令告诉了我们该结构体的大小为18h
add edx,offset new18.leader 这条指令是为了定位 leader(i) 的首地址;这也是leader(i).name的首地址。当我们要指向成员变量count的时候,还需要add edx,14h。

004010BB  |.  8990 447A4200 ||mov dword ptr ds:[eax+0x427A44],edx
这条指令一样, 0x427a44 和 offset new18.leader的地址是完全一致的。

评分

参与人数 1魔鬼币 +50 收起 理由
魔鬼作坊内部组 + 50 技术经验分享。

查看全部评分

54

主题

98

回帖

130

积分

终身VIP会员

花钱是让你服务的,不是叫你大哥 ...

Rank: 7Rank: 7Rank: 7

魔鬼币
10632
 楼主| 发表于 2011-8-30 21:46:32 | 显示全部楼层
(下)会尽量总结下,结构体的反汇编表现形式。

29

主题

72

回帖

80

积分

终身VIP会员

Rank: 7Rank: 7Rank: 7

魔鬼币
9352
发表于 2011-8-31 03:15:02 | 显示全部楼层
都看不懂你叨叨个什么劲啊 来点通俗的

29

主题

72

回帖

80

积分

终身VIP会员

Rank: 7Rank: 7Rank: 7

魔鬼币
9352
发表于 2011-8-31 03:17:01 | 显示全部楼层
看不懂 来点通俗易懂的 课本上的文字难懂是为了科学的逻辑性和严密性  咱当人的就说通俗点吧  说吧 他到底是个啥 介四个嘛玩意儿

41

主题

210

回帖

167

积分

终身VIP会员

Rank: 7Rank: 7Rank: 7

魔鬼币
36045
发表于 2011-8-31 12:06:56 | 显示全部楼层
朋友,赚了多少钱了
把这个当成个爱好就行了,别拿这个养家糊口。

41

主题

210

回帖

167

积分

终身VIP会员

Rank: 7Rank: 7Rank: 7

魔鬼币
36045
发表于 2011-8-31 12:07:59 | 显示全部楼层
我现在好长时间没接触OD了,忙呢。

67

主题

208

回帖

359

积分

终身VIP会员

Rank: 7Rank: 7Rank: 7

魔鬼币
28488
发表于 2014-2-14 13:41:58 | 显示全部楼层
呵呵,写代码,看汇编 === 观察如何变形
您需要登录后才可以回帖 登录 | 点击注册

本版积分规则

魔鬼作坊|易语言教程|易语言源码|易语言论坛|易语言视频教程| 论坛导航|免责申明|手机版||网站地图
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表魔鬼作坊立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2010-2019 All Right Reserved.
快速回复 返回顶部 返回列表