forked from thomasxm/shellcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlzoma_depack_x86.asm
More file actions
180 lines (159 loc) · 5.14 KB
/
lzoma_depack_x86.asm
File metadata and controls
180 lines (159 loc) · 5.14 KB
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
;
; LZOMA depacker in x86 assembly, by odzhan in 238 bytes.
;
; Last modified: 14/03/2020
;
; void lzoma_depack(void *outbuf, uint32_t inlen, const void *inbuf);
;
bits 32
struc pushad_t
._edi resd 1
._esi resd 1
._ebp resd 1
._esp resd 1
._ebx resd 1
._edx resd 1
._ecx resd 1
._eax resd 1
endstruc
%ifndef BIN
global lzoma_depackx
global _lzoma_depackx
%endif
lzoma_depackx:
_lzoma_depackx:
pushad ; save all registers
lea esi, [esp+32+4]
lodsd
xchg edi, eax ; edi = outbuf
lodsd
xchg ebp, eax ; ebp = inlen
add ebp, edi ; ebp += out
lodsd
xchg esi, eax ; esi = inbuf
pushad ; save esi, edi and ebp
call init_getbit
get_bit:
add eax, eax ; c->w <<= 1
jnz exit_getbit ; if(c->w == 0)
lodsd ; x = *(uint32_t*)c->src;
adc eax, eax ; c->w = (x << 1) | 1;
exit_getbit:
ret ; return x >> 31;
init_getbit:
pop ebp ; ebp = &get_bit
mov eax, 1 << 31 ; c->w = 1 << 31
cdq ; ofs = -1
movsb ; *out++ = *src++;
xor ecx, ecx ; len = 0
jmp main_loop
copy_byte:
movsb ; *out++ = *c.src++;
mov cl, 2 ; len = 2
main_loop:
xor ebx, ebx ; res = 0
; while(out < end)
cmp edi, [esp+pushad_t._ebp]
jnb lzoma_exit
; for(;;) {
call ebp ; cf = get_bit(&c);
jnc copy_byte ; if(cf) break;
; unpack lz
jecxz skip_lz ; if(len) {
call ebp ; cf = get_bit(&c);
skip_lz: ; }
; carry?
jnc use_last_offset ; if(cf) {
mov cl, 3+2 ; len = 3
pushad ;
; total = out - (uint8_t*)outbuf
sub edi, [esp+32+pushad_t._edi]
; top = ((total <= 400000) ? 60 : 50;
mov cl, 50
cmp edi, 400000
ja skip_upd
add cl, 10
skip_upd:
xor ebp, ebp ; ofs = 0
xor edx, edx ; x = 256
inc dh
mov bl, byte[esi] ; res = *c.src++
inc esi
find_loop: ; for(;;) {
add edx, edx ; x += x;
; if(x >= (total + top)) {
push edi ; save total
add edi, ecx ; edi = total + top
cmp edx, edi ; cf = (x - (total + top))
pop edi ; restore total
jb upd_len3 ; jump if x is < (total + top)
sub edx, edi ; x -= total;
cmp ebx, edx ; if(res >= x) {
jb upd_len2 ; jump if res < x
; cf = get_bit(&c);
call dword[esp+pushad_t._ebp]
adc ebx, ebx ; res = (res << 1) + cf;
sub ebx, edx ; res -= x;
jmp upd_len2
upd_len3:
; magic?
; if(x & (0x002FFE00 << 1)) {
test edx, (0x002FFE00 << 1)
jz upd_len4
; top = (((top << 3) + top) >> 3);
lea ecx, [ecx+ecx*8]
shr ecx, 3
upd_len4:
cmp ebx, ecx ; if(res < top) break;
jb upd_len2
sub ebp, ecx ; ofs -= top
add edi, ecx ; total += top
add ecx, ecx ; top <<= 1
; cf = get_bit(&c);
call dword[esp+pushad_t._ebp]
; res = (res << 1) + cf;
adc ebx, ebx
jmp find_loop
upd_len2:
; ofs = (ofs + res + 1);
lea ebp, [ebp + ebx + 1]
; if(ofs >= 5400) len++;
cmp ebp, 5400
sbb dword[esp+pushad_t._ecx], 0
; if(ofs >= 0x060000) len++;
cmp ebp, 0x060000
sbb dword[esp+pushad_t._ecx], 0
neg ebp ; ofs = -ofs;
mov [esp+pushad_t._edx], ebp ; save ofs in edx
mov [esp+pushad_t._esi], esi
mov [esp+pushad_t._eax], eax
popad ; restore registers
use_last_offset:
call ebp ; if(get_bit(&c)) {
jnc check_two
add ecx, 2 ; len += 2
upd_len: ; for(res=0;;res++) {
call ebp ; cf = get_bit(&c);
adc ebx, ebx ; res = (res << 1) + cf;
call ebp ; if(!get_bit(&c)) break;
jnc upd_lenx
inc ebx ; res++;
jmp upd_len
upd_lenx:
add ecx, ebx ; len += res
jmp copy_bytes
check_two: ; } else {
call ebp ; cf = get_bit();
adc ecx, ebx ; len += cf
copy_bytes: ; }
push esi ; save c.src pointer
lea esi, [edi + edx] ; ptr = out + ofs
dec ecx
; while(--len) *out++ = *ptr++;
rep movsb
pop esi ; restore c.src
jmp main_loop
lzoma_exit:
popad ; free()
popad ; restore registers
ret