首页
社区
课程
招聘
6
[旧帖] [分享]第二波:memcpy() 函数逆向与分析 0.00雪花
发表于: 2011-9-6 18:36 5020

[旧帖] [分享]第二波:memcpy() 函数逆向与分析 0.00雪花

2011-9-6 18:36
5020

上一次逆了 ntdll!memcpy_s() 函数,里面最终调用 ntdll!memcpy() 进行复制,这次将 ntdll!memcpy() 作为对象,进行逆向和分析。



下面是 windows 7 x64 里的 ntdll!memcpy() 函数:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
ntdll!memcpy:
00000000`77a7e6d0 4c8bd9          mov     r11,rcx
00000000`77a7e6d3 482bd1          sub     rdx,rcx
00000000`77a7e6d6 0f829e010000    jb      ntdll!memcpy+0x1aa (00000000`77a7e87a)
 
ntdll!memcpy+0xc:
00000000`77a7e6dc 4983f808        cmp     r8,8
00000000`77a7e6e0 7262            jb      ntdll!memcpy+0x74 (00000000`77a7e744)
 
ntdll!memcpy+0x12:
00000000`77a7e6e2 f6c107          test    cl,7
00000000`77a7e6e5 7437            je      ntdll!memcpy+0x4e (00000000`77a7e71e)
 
ntdll!memcpy+0x17:
00000000`77a7e6e7 f6c101          test    cl,1
00000000`77a7e6ea 740c            je      ntdll!memcpy+0x28 (00000000`77a7e6f8)
 
ntdll!memcpy+0x1c:
00000000`77a7e6ec 8a040a          mov     al,byte ptr [rdx+rcx]
00000000`77a7e6ef 49ffc8          dec     r8
00000000`77a7e6f2 8801            mov     byte ptr [rcx],al
00000000`77a7e6f4 4883c101        add     rcx,1
 
ntdll!memcpy+0x28:
00000000`77a7e6f8 f6c102          test    cl,2
00000000`77a7e6fb 740f            je      ntdll!memcpy+0x3c (00000000`77a7e70c)
 
ntdll!memcpy+0x2d:
00000000`77a7e6fd 668b040a        mov     ax,word ptr [rdx+rcx]
00000000`77a7e701 4983e802        sub     r8,2
00000000`77a7e705 668901          mov     word ptr [rcx],ax
00000000`77a7e708 4883c102        add     rcx,2
 
ntdll!memcpy+0x3c:
00000000`77a7e70c f6c104          test    cl,4
00000000`77a7e70f 740d            je      ntdll!memcpy+0x4e (00000000`77a7e71e)
 
ntdll!memcpy+0x41:
00000000`77a7e711 8b0411          mov     eax,dword ptr [rcx+rdx]
00000000`77a7e714 4983e804        sub     r8,4
00000000`77a7e718 8901            mov     dword ptr [rcx],eax
00000000`77a7e71a 4883c104        add     rcx,4
 
ntdll!memcpy+0x4e:
00000000`77a7e71e 4d8bc8          mov     r9,r8
00000000`77a7e721 49c1e905        shr     r9,5
00000000`77a7e725 7550            jne     ntdll!memcpy+0xa7 (00000000`77a7e777)
 
ntdll!memcpy+0x57:
00000000`77a7e727 4d8bc8          mov     r9,r8
00000000`77a7e72a 49c1e903        shr     r9,3
00000000`77a7e72e 7414            je      ntdll!memcpy+0x74 (00000000`77a7e744)
 
ntdll!memcpy+0x60:
00000000`77a7e730 488b040a        mov     rax,qword ptr [rdx+rcx]
00000000`77a7e734 488901          mov     qword ptr [rcx],rax
00000000`77a7e737 4883c108        add     rcx,8
00000000`77a7e73b 49ffc9          dec     r9
00000000`77a7e73e 75f0            jne     ntdll!memcpy+0x60 (00000000`77a7e730)
 
ntdll!memcpy+0x70:
00000000`77a7e740 4983e007        and     r8,7
 
ntdll!memcpy+0x74:
00000000`77a7e744 4d85c0          test    r8,r8
00000000`77a7e747 7507            jne     ntdll!memcpy+0x80 (00000000`77a7e750)
 
ntdll!memcpy+0x79:
00000000`77a7e749 498bc3          mov     rax,r11
00000000`77a7e74c c3              ret
 
ntdll!memcpy+0x80:
00000000`77a7e750 8a040a          mov     al,byte ptr [rdx+rcx]
00000000`77a7e753 8801            mov     byte ptr [rcx],al
00000000`77a7e755 48ffc1          inc     rcx
00000000`77a7e758 49ffc8          dec     r8
00000000`77a7e75b 75f3            jne     ntdll!memcpy+0x80 (00000000`77a7e750)
 
ntdll!memcpy+0x8d:
00000000`77a7e75d 498bc3          mov     rax,r11
00000000`77a7e760 c3              ret
 
ntdll!memcpy+0xa7:
00000000`77a7e777 4981f900200000  cmp     r9,2000h
00000000`77a7e77e 7342            jae     ntdll!memcpy+0xf2 (00000000`77a7e7c2)
 
ntdll!memcpy+0xb0:
00000000`77a7e780 488b040a        mov     rax,qword ptr [rdx+rcx]
00000000`77a7e784 4c8b540a08      mov     r10,qword ptr [rdx+rcx+8]
00000000`77a7e789 4883c120        add     rcx,20h
00000000`77a7e78d 488941e0        mov     qword ptr [rcx-20h],rax
00000000`77a7e791 4c8951e8        mov     qword ptr [rcx-18h],r10
00000000`77a7e795 488b440af0      mov     rax,qword ptr [rdx+rcx-10h]
00000000`77a7e79a 4c8b540af8      mov     r10,qword ptr [rdx+rcx-8]
00000000`77a7e79f 49ffc9          dec     r9
00000000`77a7e7a2 488941f0        mov     qword ptr [rcx-10h],rax
00000000`77a7e7a6 4c8951f8        mov     qword ptr [rcx-8],r10
00000000`77a7e7aa 75d4            jne     ntdll!memcpy+0xb0 (00000000`77a7e780)
 
ntdll!memcpy+0xdc:
00000000`77a7e7ac 4983e01f        and     r8,1Fh
00000000`77a7e7b0 e972ffffff      jmp     ntdll!memcpy+0x57 (00000000`77a7e727)
 
ntdll!memcpy+0xf2:
00000000`77a7e7c2 4881fa00100000  cmp     rdx,1000h
00000000`77a7e7c9 72b5            jb      ntdll!memcpy+0xb0 (00000000`77a7e780)
 
ntdll!memcpy+0xfb:
00000000`77a7e7cb b820000000      mov     eax,20h
 
ntdll!memcpy+0x100:
00000000`77a7e7d0 0f18040a        prefetchnta [rdx+rcx]
00000000`77a7e7d4 0f18440a40      prefetchnta [rdx+rcx+40h]
00000000`77a7e7d9 4881c180000000  add     rcx,80h
00000000`77a7e7e0 ffc8            dec     eax
00000000`77a7e7e2 75ec            jne     ntdll!memcpy+0x100 (00000000`77a7e7d0)
 
ntdll!memcpy+0x114:
00000000`77a7e7e4 4881e900100000  sub     rcx,1000h
00000000`77a7e7eb b840000000      mov     eax,40h
 
ntdll!memcpy+0x120:
00000000`77a7e7f0 4c8b0c0a        mov     r9,qword ptr [rdx+rcx]
00000000`77a7e7f4 4c8b540a08      mov     r10,qword ptr [rdx+rcx+8]
00000000`77a7e7f9 4c0fc309        movnti  qword ptr [rcx],r9
00000000`77a7e7fd 4c0fc35108      movnti  qword ptr [rcx+8],r10
00000000`77a7e802 4c8b4c0a10      mov     r9,qword ptr [rdx+rcx+10h]
00000000`77a7e807 4c8b540a18      mov     r10,qword ptr [rdx+rcx+18h]
00000000`77a7e80c 4c0fc34910      movnti  qword ptr [rcx+10h],r9
00000000`77a7e811 4c0fc35118      movnti  qword ptr [rcx+18h],r10
00000000`77a7e816 4c8b4c0a20      mov     r9,qword ptr [rdx+rcx+20h]
00000000`77a7e81b 4c8b540a28      mov     r10,qword ptr [rdx+rcx+28h]
00000000`77a7e820 4883c140        add     rcx,40h
00000000`77a7e824 4c0fc349e0      movnti  qword ptr [rcx-20h],r9
00000000`77a7e829 4c0fc351e8      movnti  qword ptr [rcx-18h],r10
00000000`77a7e82e 4c8b4c0af0      mov     r9,qword ptr [rdx+rcx-10h]
00000000`77a7e833 4c8b540af8      mov     r10,qword ptr [rdx+rcx-8]
00000000`77a7e838 ffc8            dec     eax
00000000`77a7e83a 4c0fc349f0      movnti  qword ptr [rcx-10h],r9
00000000`77a7e83f 4c0fc351f8      movnti  qword ptr [rcx-8],r10
00000000`77a7e844 75aa            jne     ntdll!memcpy+0x120 (00000000`77a7e7f0)
 
ntdll!memcpy+0x176:
00000000`77a7e846 4981e800100000  sub     r8,1000h
00000000`77a7e84d 4981f800100000  cmp     r8,1000h
00000000`77a7e854 0f8371ffffff    jae     ntdll!memcpy+0xfb (00000000`77a7e7cb)
 
ntdll!memcpy+0x18a:
00000000`77a7e85a f0800c2400      lock or byte ptr [rsp],0
00000000`77a7e85f e9bafeffff      jmp     ntdll!memcpy+0x4e (00000000`77a7e71e)
 
ntdll!memcpy+0x1aa:
00000000`77a7e87a 4903c8          add     rcx,r8
00000000`77a7e87d 4983f808        cmp     r8,8
00000000`77a7e881 7261            jb      ntdll!memcpy+0x214 (00000000`77a7e8e4)
 
ntdll!memcpy+0x1b3:
00000000`77a7e883 f6c107          test    cl,7
00000000`77a7e886 7436            je      ntdll!memcpy+0x1ee (00000000`77a7e8be)
 
ntdll!memcpy+0x1b8:
00000000`77a7e888 f6c101          test    cl,1
00000000`77a7e88b 740b            je      ntdll!memcpy+0x1c8 (00000000`77a7e898)
 
ntdll!memcpy+0x1bd:
00000000`77a7e88d 48ffc9          dec     rcx
00000000`77a7e890 8a040a          mov     al,byte ptr [rdx+rcx]
00000000`77a7e893 49ffc8          dec     r8
00000000`77a7e896 8801            mov     byte ptr [rcx],al
 
ntdll!memcpy+0x1c8:
00000000`77a7e898 f6c102          test    cl,2
00000000`77a7e89b 740f            je      ntdll!memcpy+0x1dc (00000000`77a7e8ac)
 
ntdll!memcpy+0x1cd:
00000000`77a7e89d 4883e902        sub     rcx,2
00000000`77a7e8a1 668b040a        mov     ax,word ptr [rdx+rcx]
00000000`77a7e8a5 4983e802        sub     r8,2
00000000`77a7e8a9 668901          mov     word ptr [rcx],ax
 
ntdll!memcpy+0x1dc:
00000000`77a7e8ac f6c104          test    cl,4
00000000`77a7e8af 740d            je      ntdll!memcpy+0x1ee (00000000`77a7e8be)
 
ntdll!memcpy+0x1e1:
00000000`77a7e8b1 4883e904        sub     rcx,4
00000000`77a7e8b5 8b0411          mov     eax,dword ptr [rcx+rdx]
00000000`77a7e8b8 4983e804        sub     r8,4
00000000`77a7e8bc 8901            mov     dword ptr [rcx],eax
 
ntdll!memcpy+0x1ee:
00000000`77a7e8be 4d8bc8          mov     r9,r8
00000000`77a7e8c1 49c1e905        shr     r9,5
00000000`77a7e8c5 7550            jne     ntdll!memcpy+0x247 (00000000`77a7e917)
 
ntdll!memcpy+0x1f7:
00000000`77a7e8c7 4d8bc8          mov     r9,r8
00000000`77a7e8ca 49c1e903        shr     r9,3
00000000`77a7e8ce 7414            je      ntdll!memcpy+0x214 (00000000`77a7e8e4)
 
ntdll!memcpy+0x200:
00000000`77a7e8d0 4883e908        sub     rcx,8
00000000`77a7e8d4 488b040a        mov     rax,qword ptr [rdx+rcx]
00000000`77a7e8d8 49ffc9          dec     r9
00000000`77a7e8db 488901          mov     qword ptr [rcx],rax
00000000`77a7e8de 75f0            jne     ntdll!memcpy+0x200 (00000000`77a7e8d0)
 
ntdll!memcpy+0x210:
00000000`77a7e8e0 4983e007        and     r8,7
 
ntdll!memcpy+0x214:
00000000`77a7e8e4 4d85c0          test    r8,r8
00000000`77a7e8e7 7507            jne     ntdll!memcpy+0x220 (00000000`77a7e8f0)
 
ntdll!memcpy+0x219:
00000000`77a7e8e9 498bc3          mov     rax,r11
00000000`77a7e8ec c3              ret
 
ntdll!memcpy+0x220:
00000000`77a7e8f0 48ffc9          dec     rcx
00000000`77a7e8f3 8a040a          mov     al,byte ptr [rdx+rcx]
00000000`77a7e8f6 49ffc8          dec     r8
00000000`77a7e8f9 8801            mov     byte ptr [rcx],al
00000000`77a7e8fb 75f3            jne     ntdll!memcpy+0x220 (00000000`77a7e8f0)
 
ntdll!memcpy+0x22d:
00000000`77a7e8fd 498bc3          mov     rax,r11
00000000`77a7e900 c3              ret
 
ntdll!memcpy+0x247:
00000000`77a7e917 4981f900200000  cmp     r9,2000h
00000000`77a7e91e 7342            jae     ntdll!memcpy+0x292 (00000000`77a7e962)
 
ntdll!memcpy+0x250:
00000000`77a7e920 488b440af8      mov     rax,qword ptr [rdx+rcx-8]
00000000`77a7e925 4c8b540af0      mov     r10,qword ptr [rdx+rcx-10h]
00000000`77a7e92a 4883e920        sub     rcx,20h
00000000`77a7e92e 48894118        mov     qword ptr [rcx+18h],rax
00000000`77a7e932 4c895110        mov     qword ptr [rcx+10h],r10
00000000`77a7e936 488b440a08      mov     rax,qword ptr [rdx+rcx+8]
00000000`77a7e93b 4c8b140a        mov     r10,qword ptr [rdx+rcx]
00000000`77a7e93f 49ffc9          dec     r9
00000000`77a7e942 48894108        mov     qword ptr [rcx+8],rax
00000000`77a7e946 4c8911          mov     qword ptr [rcx],r10
00000000`77a7e949 75d5            jne     ntdll!memcpy+0x250 (00000000`77a7e920)
 
ntdll!memcpy+0x27b:
00000000`77a7e94b 4983e01f        and     r8,1Fh
00000000`77a7e94f e973ffffff      jmp     ntdll!memcpy+0x1f7 (00000000`77a7e8c7)
 
ntdll!memcpy+0x292:
00000000`77a7e962 4881fa00f0ffff  cmp     rdx,0FFFFFFFFFFFFF000h
00000000`77a7e969 77b5            ja      ntdll!memcpy+0x250 (00000000`77a7e920)
 
ntdll!memcpy+0x29b:
00000000`77a7e96b b820000000      mov     eax,20h
 
ntdll!memcpy+0x2a0:
00000000`77a7e970 4881e980000000  sub     rcx,80h
00000000`77a7e977 0f18040a        prefetchnta [rdx+rcx]
00000000`77a7e97b 0f18440a40      prefetchnta [rdx+rcx+40h]
00000000`77a7e980 ffc8            dec     eax
00000000`77a7e982 75ec            jne     ntdll!memcpy+0x2a0 (00000000`77a7e970)
 
ntdll!memcpy+0x2b4:
00000000`77a7e984 4881c100100000  add     rcx,1000h
00000000`77a7e98b b840000000      mov     eax,40h
 
ntdll!memcpy+0x2c0:
00000000`77a7e990 4c8b4c0af8      mov     r9,qword ptr [rdx+rcx-8]
00000000`77a7e995 4c8b540af0      mov     r10,qword ptr [rdx+rcx-10h]
00000000`77a7e99a 4c0fc349f8      movnti  qword ptr [rcx-8],r9
00000000`77a7e99f 4c0fc351f0      movnti  qword ptr [rcx-10h],r10
00000000`77a7e9a4 4c8b4c0ae8      mov     r9,qword ptr [rdx+rcx-18h]
00000000`77a7e9a9 4c8b540ae0      mov     r10,qword ptr [rdx+rcx-20h]
00000000`77a7e9ae 4c0fc349e8      movnti  qword ptr [rcx-18h],r9
00000000`77a7e9b3 4c0fc351e0      movnti  qword ptr [rcx-20h],r10
00000000`77a7e9b8 4c8b4c0ad8      mov     r9,qword ptr [rdx+rcx-28h]
00000000`77a7e9bd 4c8b540ad0      mov     r10,qword ptr [rdx+rcx-30h]
00000000`77a7e9c2 4883e940        sub     rcx,40h
00000000`77a7e9c6 4c0fc34918      movnti  qword ptr [rcx+18h],r9
00000000`77a7e9cb 4c0fc35110      movnti  qword ptr [rcx+10h],r10
00000000`77a7e9d0 4c8b4c0a08      mov     r9,qword ptr [rdx+rcx+8]
00000000`77a7e9d5 4c8b140a        mov     r10,qword ptr [rdx+rcx]
00000000`77a7e9d9 ffc8            dec     eax
00000000`77a7e9db 4c0fc34908      movnti  qword ptr [rcx+8],r9
00000000`77a7e9e0 4c0fc311        movnti  qword ptr [rcx],r10
00000000`77a7e9e4 75aa            jne     ntdll!memcpy+0x2c0 (00000000`77a7e990)
 
ntdll!memcpy+0x316:
00000000`77a7e9e6 4981e800100000  sub     r8,1000h
00000000`77a7e9ed 4981f800100000  cmp     r8,1000h
00000000`77a7e9f4 0f8371ffffff    jae     ntdll!memcpy+0x29b (00000000`77a7e96b)
 
ntdll!memcpy+0x32a:
00000000`77a7e9fa f0800c2400      lock or byte ptr [rsp],0
00000000`77a7e9ff e9bafeffff      jmp     ntdll!memcpy+0x1ee (00000000`77a7e8be)



这个函数比较长,在 ntdll 模块里,因此对于效率的要求是很高的,它的函数原型,类似下面:


1
char *memcpy(char *dest, char *source, unsigned long long count);


这个 count 实际上是 

64

 位值,在上一篇逆向中用了 

unsigned int

 (32 位值)



1. memcpy() 分两大情况进行处理



memcpy() 会首先判断 dest 和 source 的位置:



00000000`77a7e6d0 4c8bd9          mov     r11,rcx


00000000`77a7e6d3 482bd1          

sub     rdx,rcx


00000000`77a7e6d6 0f829e010000    

jb      ntdll!memcpy+0x1aa 

(00000000`77a7e87a)



ntdll!memcpy+0xc:


00000000`77a7e6dc 4983f808        cmp     r8,8


00000000`77a7e6e0 7262            jb      ntdll!memcpy+0x74 (00000000`77a7e744) 



... ... 



ntdll!memcpy+0x1aa:


00000000`77a7e87a 4903c8          add     rcx,r8


00000000`77a7e87d 4983f808        cmp     r8,8


00000000`77a7e881 7261            jb      ntdll!memcpy+0x214 (00000000`77a7e8e4)



第1种情况是: source >= dest 的时候,第 2 种情况是:source < dest 的时候,在这里我们得到下面的逻辑:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char *memcpy(char *dest, char *source, unsigned long long count)
{
    char *p = dest;
 
    if (source >= dest)
    {
          // 相关处理
    }
    else
    {
         // 相关处理
    }
 
 
    return p;
}



这里,我主要对 source >= dest 这种情况进行分析,后面的 source < dest  处理手法完全是一样的。



2.  当 count 小于 8 的时候



接下来,首先处理当复制数量小于 8 bytes 时,在这种情况肯定是最简单的:



ntdll!memcpy+0xc:


00000000`77a7e6dc 4983f808        

cmp     r8,8

                          ; count < 8 时候


00000000`77a7e6e0 7262            jb      ntdll!memcpy+0x74 (00000000`77a7e744)



... ...



ntdll!memcpy+0x74:


00000000`77a7e744 4d85c0          test    r8,r8


00000000`77a7e747 7507            jne     ntdll!memcpy+0x80 (00000000`77a7e750)



... ...



ntdll!memcpy+0x80:


00000000`77a7e750 8a040a          mov     al,byte ptr [rdx+rcx]


00000000`77a7e753 8801            mov     byte ptr [rcx],al


00000000`77a7e755 48ffc1          inc     rcx


00000000`77a7e758 49ffc8          dec     r8


00000000`77a7e75b 75f3            jne     ntdll!memcpy+0x80 (00000000`77a7e750)



ntdll!memcpy+0x8d:


00000000`77a7e75d 498bc3          mov     rax,r11


00000000`77a7e760 c3              ret



当小于 8 时候只是做简单的复制就可以了,于是,我们得到下面的逻辑:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char *memcpy(char *dest, char *source, unsigned long long count)
{
    char *p = dest;
 
    if (source >= dest)
    {
           
         if (count < 8)
         {
             while (count--)
                 *dest++ = *source++;    
         }
     
 
    }
    else
    {
         // 相关处理
    }
 
 
    return p;
}



3. 处理地址非对齐的情况



我们都知道,当复制进候,源地址和目标地址都是

对齐

的情况下,效率是最高的。


当然这是一种理想的状态,实际上我们会遇到非对齐的地址,那么 memcpy() 会怎样处理呢:



ntdll!memcpy+0x12:


00000000`77a7e6e2 f6c107          test    cl,7


00000000`77a7e6e5 7437            je      ntdll!memcpy+0x4e (00000000`77a7e71e)



ntdll!memcpy+0x17:


00000000`77a7e6e7 f6c101          test    cl,1


00000000`77a7e6ea 740c            je      ntdll!memcpy+0x28 (00000000`77a7e6f8)



ntdll!memcpy+0x1c:


00000000`77a7e6ec 8a040a          mov     al,byte ptr [rdx+rcx]


00000000`77a7e6ef 49ffc8          dec     r8


00000000`77a7e6f2 8801            mov     byte ptr [rcx],al


00000000`77a7e6f4 4883c101        add     rcx,1



ntdll!memcpy+0x28:


00000000`77a7e6f8 f6c102          test    cl,2


00000000`77a7e6fb 740f            je      ntdll!memcpy+0x3c (00000000`77a7e70c)



ntdll!memcpy+0x2d:


00000000`77a7e6fd 668b040a        mov     ax,word ptr [rdx+rcx]


00000000`77a7e701 4983e802        sub     r8,2


00000000`77a7e705 668901          mov     word ptr [rcx],ax


00000000`77a7e708 4883c102        add     rcx,2



ntdll!memcpy+0x3c:


00000000`77a7e70c f6c104          test    cl,4


00000000`77a7e70f 740d            je      ntdll!memcpy+0x4e (00000000`77a7e71e)



ntdll!memcpy+0x41:


00000000`77a7e711 8b0411          mov     eax,dword ptr [rcx+rdx]


00000000`77a7e714 4983e804        sub     r8,4


00000000`77a7e718 8901            mov     dword ptr [rcx],eax


00000000`77a7e71a 4883c104        add     rcx,4



上面一段代码都是在处理当目标地址处理非对齐的情况下,memcpy() 的处理手法是:

在进行大批量复制之前,先处理掉非对齐的部分,从而变得对齐了



上面这段代码的逻辑是:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  if (dest & 0x07)
  {
    if (dest & 0x01)
    {
      *dest++ = *source++;
      count--;
    }
 
    if (dest & 0x02)
    {
      *dest++ = *source++;
      *dest++ = *source++;
      count -= 2;
    }
 
    if (dest & 0x04)
    {
      *(int *)dest++ = *(int *)source++;
      count -= 4;
    }
  }



这段代码的作用是对非对齐地址进行填补,我们可以把代码写得好看些:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
char *memcpy(char *dest, char *source, unsigned long long count)
{
    char *p = dest;
 
    if (source >= dest)
    {
           
         if (count < 8)
         {
             while (count--)
                 *dest++ = *source++;    
         }
 
         
[B]        swtich (dest & 0x07)
        {
        case 7:        *dest++ = *source++;  count--;
        case 6:        *dest++ = *source++;  count--;
        case 5:        *dest++ = *source++;  count--;
        case 4:        *dest++ = *source++;  count--;
        case 3:        *dest++ = *source++;  count--;
        case 2:        *dest++ = *source++;  count--;
        case 1:        *dest++ = *source++;  count--;
        } [/B]               
 
 
    }
    else
    {
         // 相关处理
    }
 
 
    return p;
}



4. 当 count 小于 32 的情况下,以 32 bytes 作为一个处理单元



接下来会根据将 count 分为几种情况,首先是以 32 bytes 作为一个处理单元:



ntdll!memcpy+0x4e:


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

收藏
免费 6
支持
分享
赞赏记录
参与人
雪币
留言
时间
伟叔叔
为你点赞~
2024-5-31 02:08
心游尘世外
为你点赞~
2024-3-3 04:05
飘零丶
为你点赞~
2024-2-25 00:10
QinBeast
为你点赞~
2024-1-29 01:53
shinratensei
为你点赞~
2024-1-23 03:50
PLEBFE
为你点赞~
2023-3-7 01:32
最新回复 (22)
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
memcpy() 大概分析完,后面有些马虎了,早早了事,将就将就
2011-9-6 18:38
0
雪    币: 152
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
复杂。就一个memcpy
2011-9-6 18:55
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
看过上一篇,表示支持。
2011-9-6 19:04
0
雪    币: 1149
活跃值: (1003)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
5
如果仅仅是为了学习 练手的话,我支持一下,如果能力是在逆这个函数之上的话,我觉得 你应该做一些 有意思的东西,比如分析一些恶意代码 然后分享。。

我觉得这样 对己对彼 都十分 有进步............

随便说说,lz 加油!
2011-9-6 19:39
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
6
楼主加油
2011-9-6 20:33
0
雪    币: 7374
活跃值: (1340)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼主加油,顺便学习下!
2011-9-6 22:14
0
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
友善地问一下,这种能得邀请码吗?

注册几天了,还没搞到邀请码。
2011-9-7 01:53
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习了,学习了
2011-9-7 06:31
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
刚刚开始学习,支持! 谢谢楼主!
2011-9-7 08:06
0
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
不错,留下脚印,慢慢了解
2011-9-7 08:14
0
雪    币: 237
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
很好。
分析善意比分析恶意有意义,鼓励lz再接再励。
2011-9-7 14:14
0
雪    币: 86
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这些函数都不用逆,都有现成源码,下个ReactOS源码,crt目录,这些库函数都有源码

就连微软提供的SDK,这些源码都有
2011-9-7 21:21
0
雪    币: 324
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
分析到底层去了啊,这样对与提升自己的编程水平还是很有帮助的
2011-9-7 21:30
0
雪    币: 196
活跃值: (135)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
15
先鼓励一下楼主的劳动,但是楼主的代码里有一个很明显的错误,希望以后能更细心一些.
if (count >= 8)
                {
                        for (int i = count / 8; i; i++)
                                *(long long *)dest++ = *(long long *)source++;        

                        for (int i = count % 8; i; i++)        
                                *dest++ = *source++;
                }
2011-9-8 09:27
0
雪    币: 623
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
16
赞一下楼上,看贴很认真,多谢指出:

改为:

for (int i = 0; i < count / 8; i++)
        *(long long *)dest++ = *(long long *)source++;

for (int i = 0; i < count %8; i++)
        *dest++ = *source++;

或者:

for (int i = count / 8; i; i--)
        *(long long *)dest++ = *(long long *)source++;

for (int i = count % 8; i; i--)
        *dest++ = *source++;
2011-9-8 09:47
0
雪    币: 555
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
有点深奥,学习了,谢谢
2011-9-8 15:08
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
哇塞,太高深了,看不懂,膜拜LZ
2011-9-10 10:01
0
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
不是有源码吗
2011-9-12 08:40
0
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
支持下楼主,memcpy函数确实属于比较复杂的一个函数
2011-9-14 08:44
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
学习了~~这个函数有源码
2011-9-14 22:09
0
雪    币: 160
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
linux 里面应该有实现源码!
2011-9-18 22:41
0
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
lz厉害,学习学习
2011-9-19 10:11
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册