Coverage Report

Created: 2023-12-08 06:48

/src/clamav/libclamav/packlibs.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (C) 2013-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
 *  Copyright (C) 2007-2013 Sourcefire, Inc.
4
 *
5
 *  Authors: Alberto Wu, Michal 'GiM' Spadlinski
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License version 2 as
9
 *  published by the Free Software Foundation.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 *  MA 02110-1301, USA.
20
 */
21
22
#if HAVE_CONFIG_H
23
#include "clamav-config.h"
24
#endif
25
26
#include "clamav.h"
27
#include "others.h"
28
#include "execs.h"
29
#include "pe.h"
30
#include "packlibs.h"
31
32
static int doubledl(const char **scur, uint8_t *mydlptr, const char *buffer, uint32_t buffersize)
33
181k
{
34
181k
    unsigned char mydl  = *mydlptr;
35
181k
    unsigned char olddl = mydl;
36
37
181k
    mydl *= 2;
38
181k
    if (!(olddl & 0x7f)) {
39
23.2k
        if (*scur < buffer || *scur >= buffer + buffersize - 1)
40
1
            return -1;
41
23.2k
        olddl = **scur;
42
23.2k
        mydl  = olddl * 2 + 1;
43
23.2k
        *scur = *scur + 1;
44
23.2k
    }
45
181k
    *mydlptr = mydl;
46
181k
    return (olddl >> 7) & 1;
47
181k
}
48
49
int cli_unfsg(const char *source, char *dest, int ssize, int dsize, const char **endsrc, char **enddst)
50
0
{
51
0
    uint8_t mydl = 0x80;
52
0
    uint32_t backbytes, backsize, oldback = 0;
53
0
    const char *csrc = source;
54
0
    char *cdst       = dest;
55
0
    int oob, lostbit = 1;
56
57
0
    if (ssize <= 0 || dsize <= 0) return -1;
58
0
    *cdst++ = *csrc++;
59
60
0
    while (1) {
61
0
        if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
62
0
            if (oob == -1)
63
0
                return -1;
64
            /* 164 */
65
0
            backsize = 0;
66
0
            if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
67
0
                if (oob == -1)
68
0
                    return -1;
69
                /* 16a */
70
0
                backbytes = 0;
71
0
                if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
72
0
                    if (oob == -1)
73
0
                        return -1;
74
                    /* 170 */
75
0
                    lostbit = 1;
76
0
                    backsize++;
77
0
                    backbytes = 0x10;
78
0
                    while (backbytes < 0x100) {
79
0
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
80
0
                            return -1;
81
0
                        backbytes = backbytes * 2 + oob;
82
0
                    }
83
0
                    backbytes &= 0xff;
84
0
                    if (!backbytes) {
85
0
                        if (cdst >= dest + dsize)
86
0
                            return -1;
87
0
                        *cdst++ = 0x00;
88
0
                        continue;
89
0
                    }
90
0
                } else {
91
                    /* 18f */
92
0
                    if (csrc >= source + ssize)
93
0
                        return -1;
94
0
                    backbytes = *(unsigned char *)csrc;
95
0
                    backsize  = backsize * 2 + (backbytes & 1);
96
0
                    backbytes = (backbytes & 0xff) >> 1;
97
0
                    csrc++;
98
0
                    if (!backbytes)
99
0
                        break;
100
0
                    backsize += 2;
101
0
                    oldback = backbytes;
102
0
                    lostbit = 0;
103
0
                }
104
0
            } else {
105
                /* 180 */
106
0
                backsize = 1;
107
0
                do {
108
0
                    if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
109
0
                        return -1;
110
0
                    backsize = backsize * 2 + oob;
111
0
                    if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
112
0
                        return -1;
113
0
                } while (oob);
114
115
0
                backsize = backsize - 1 - lostbit;
116
0
                if (!backsize) {
117
                    /* 18a */
118
0
                    backsize = 1;
119
0
                    do {
120
0
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
121
0
                            return -1;
122
0
                        backsize = backsize * 2 + oob;
123
0
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
124
0
                            return -1;
125
0
                    } while (oob);
126
127
0
                    backbytes = oldback;
128
0
                } else {
129
                    /* 198 */
130
0
                    if (csrc >= source + ssize)
131
0
                        return -1;
132
0
                    backbytes = *(unsigned char *)csrc;
133
0
                    backbytes += (backsize - 1) << 8;
134
0
                    backsize = 1;
135
0
                    csrc++;
136
0
                    do {
137
0
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
138
0
                            return -1;
139
0
                        backsize = backsize * 2 + oob;
140
0
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
141
0
                            return -1;
142
0
                    } while (oob);
143
144
0
                    if (backbytes >= 0x7d00)
145
0
                        backsize++;
146
0
                    if (backbytes >= 0x500)
147
0
                        backsize++;
148
0
                    if (backbytes <= 0x7f)
149
0
                        backsize += 2;
150
151
0
                    oldback = backbytes;
152
0
                }
153
0
                lostbit = 0;
154
0
            }
155
0
            if (!CLI_ISCONTAINED(dest, dsize, cdst, backsize) || !CLI_ISCONTAINED(dest, dsize, cdst - backbytes, backsize))
156
0
                return -1;
157
0
            while (backsize--) {
158
0
                *cdst = *(cdst - backbytes);
159
0
                cdst++;
160
0
            }
161
162
0
        } else {
163
            /* 15d */
164
0
            if (cdst < dest || cdst >= dest + dsize || csrc < source || csrc >= source + ssize)
165
0
                return -1;
166
0
            *cdst++ = *csrc++;
167
0
            lostbit = 1;
168
0
        }
169
0
    }
170
171
0
    if (endsrc) *endsrc = csrc;
172
0
    if (enddst) *enddst = cdst;
173
0
    return 0;
174
0
}
175
176
int unmew(const char *source, char *dest, int ssize, int dsize, const char **endsrc, char **enddst)
177
892
{
178
892
    uint8_t mydl = 0x80;
179
892
    uint32_t myeax_backbytes, myecx_backsize, oldback = 0;
180
892
    const char *csrc = source;
181
892
    char *cdst       = dest;
182
892
    int oob, lostbit = 1;
183
184
892
    *cdst++ = *csrc++;
185
186
96.4k
    while (1) {
187
96.4k
        if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
188
12.7k
            if (oob == -1)
189
1
                return -1;
190
            /* 164 */
191
12.7k
            myecx_backsize = 0;
192
12.7k
            if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
193
9.24k
                if (oob == -1)
194
0
                    return -1;
195
                /* 16a */
196
9.24k
                myeax_backbytes = 0;
197
9.24k
                if ((oob = doubledl(&csrc, &mydl, source, ssize))) {
198
7.34k
                    if (oob == -1)
199
0
                        return -1;
200
                    /* 170 */
201
7.34k
                    lostbit = 1;
202
7.34k
                    myecx_backsize++;
203
7.34k
                    myeax_backbytes = 0x10;
204
36.7k
                    while (myeax_backbytes < 0x100) {
205
29.3k
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
206
0
                            return -1;
207
29.3k
                        myeax_backbytes = myeax_backbytes * 2 + oob;
208
29.3k
                    }
209
7.34k
                    myeax_backbytes &= 0xff;
210
7.34k
                    if (!myeax_backbytes) {
211
113
                        if (cdst >= dest + dsize)
212
0
                            return -1;
213
113
                        *cdst++ = 0x00;
214
                        /*cli_dbgmsg("X%02x  ", *(cdst-1)&0xff);*/
215
113
                        continue;
216
113
                    }
217
7.34k
                } else {
218
                    /* 18f */
219
1.89k
                    if (csrc >= source + ssize)
220
0
                        return -1;
221
1.89k
                    myeax_backbytes = *(unsigned char *)csrc;
222
1.89k
                    myecx_backsize  = myecx_backsize * 2 + (myeax_backbytes & 1);
223
1.89k
                    myeax_backbytes = (myeax_backbytes & 0xff) >> 1;
224
1.89k
                    csrc++;
225
1.89k
                    if (!myeax_backbytes) {
226
                        /* cli_dbgmsg("\nBREAK \n"); */
227
557
                        break;
228
557
                    }
229
1.33k
                    myecx_backsize += 2;
230
1.33k
                    oldback = myeax_backbytes;
231
1.33k
                    lostbit = 0;
232
1.33k
                }
233
9.24k
            } else {
234
                /* 180 */
235
3.49k
                myecx_backsize = 1;
236
11.2k
                do {
237
11.2k
                    if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
238
0
                        return -1;
239
11.2k
                    myecx_backsize = myecx_backsize * 2 + oob;
240
11.2k
                    if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
241
0
                        return -1;
242
11.2k
                } while (oob);
243
244
3.49k
                myecx_backsize = myecx_backsize - 1 - lostbit;
245
3.49k
                if (!myecx_backsize) {
246
                    /* 18a */
247
979
                    myecx_backsize = 1;
248
2.23k
                    do {
249
2.23k
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
250
0
                            return -1;
251
2.23k
                        myecx_backsize = myecx_backsize * 2 + oob;
252
2.23k
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
253
0
                            return -1;
254
2.23k
                    } while (oob);
255
256
979
                    myeax_backbytes = oldback;
257
2.51k
                } else {
258
                    /* 198 */
259
2.51k
                    if (csrc >= source + ssize)
260
4
                        return -1;
261
2.50k
                    myeax_backbytes = *(unsigned char *)csrc;
262
2.50k
                    myeax_backbytes += (myecx_backsize - 1) << 8;
263
2.50k
                    myecx_backsize = 1;
264
2.50k
                    csrc++;
265
3.37k
                    do {
266
3.37k
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
267
0
                            return -1;
268
3.37k
                        myecx_backsize = myecx_backsize * 2 + oob;
269
3.37k
                        if ((oob = doubledl(&csrc, &mydl, source, ssize)) == -1)
270
0
                            return -1;
271
3.37k
                    } while (oob);
272
273
2.50k
                    if (myeax_backbytes >= 0x7d00)
274
77
                        myecx_backsize++;
275
2.50k
                    if (myeax_backbytes >= 0x500)
276
1.60k
                        myecx_backsize++;
277
2.50k
                    if (myeax_backbytes <= 0x7f)
278
364
                        myecx_backsize += 2;
279
280
2.50k
                    oldback = myeax_backbytes;
281
2.50k
                }
282
3.48k
                lostbit = 0;
283
3.48k
            }
284
12.0k
            if (!CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize) || !CLI_ISCONTAINED(dest, dsize, cdst - myeax_backbytes, myecx_backsize)) {
285
326
                cli_dbgmsg("MEW: rete: %p %d %p %d %d || %p %d %p %d %d\n", dest, dsize, cdst, myecx_backsize,
286
326
                           CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize),
287
326
                           dest, dsize, cdst - myeax_backbytes, myecx_backsize,
288
326
                           CLI_ISCONTAINED(dest, dsize, cdst - myeax_backbytes, myecx_backsize));
289
326
                return -1;
290
326
            }
291
630k
            while (myecx_backsize--) {
292
618k
                *cdst = *(cdst - myeax_backbytes);
293
618k
                cdst++;
294
618k
            }
295
296
83.7k
        } else {
297
            /* 15d */
298
83.7k
            if (cdst < dest || cdst >= dest + dsize || csrc < source || csrc >= source + ssize) {
299
4
                cli_dbgmsg("MEW: retf %p %p+%08x=%p, %p %p+%08x=%p\n",
300
4
                           cdst, dest, dsize, dest + dsize, csrc, source, ssize, source + ssize);
301
4
                return -1;
302
4
            }
303
83.7k
            *cdst++ = *csrc++;
304
            /* cli_dbgmsg("Z%02x  ", *(cdst-1)&0xff); */
305
83.7k
            lostbit = 1;
306
83.7k
        }
307
96.4k
    }
308
309
557
    *endsrc = csrc;
310
557
    *enddst = cdst;
311
557
    return 0;
312
892
}