problema de vb. ¡Gracias por la ayuda de todos!
y ejecute el lote
El lote tiene un código de retraso que espera un momento para garantizar que el programa se haya cerrado por completo
Ejecute el código de eliminación del lote
Finalmente, elimine el lote en sí
En el paso anterior, puede lograrlo
Elimine el resumen del programa en sí char buf [MAX_PATH];
Módulo HMODULE;
módulo = GetModuleHandle(0);
GetModuleFileName(módulo, buf, MAX_PATH);
CloseHandle(( HANDLE)4);
__asm
{
lea eax, buf
empuje 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push UnmapViewOfFile
ret
}
return 0;
}
Fusiona el código anterior para Win9x y WinNT/2K .
Arriba, es decir, se han ejecutado todos los códigos API utilizados por las dos plataformas. Aunque es posible que varias API no se ejecuten en una plataforma y varias API se ejecuten correctamente, el resultado final es que el archivo del programa exe se eliminará antes de salir. !
El código en Win9x y WinNT/2K es el siguiente [selfkill-9x nt.c]:
#include "windows.h"
int main (int argc, char *argv[])
{
char buf[MAX_PATH];
módulo HMODULE;
módulo = GetModuleHandle( 0);
GetModuleFileName(módulo, buf, MAX_PATH);
CloseHandle((HANDLE)4);
__asm
{
lea eax, buf
push 0
push 0
push eax
push ExitProcess
insertar módulo
insertar DeleteFile
insertar módulo
insertar UnmapViewOfFile
insertar FreeLibrary
ret
}
return 0;
}
Como aprendí el ensamblado [MASM32] en Win32, lo reescribí en ensamblador. Como resultado, todas las ejecuciones fallan y se muestra el error que se muestra en la Figura 1.
=========== Inserte la Figura 1 aquí =========. ==== =
A través de la comparación del desensamblaje, se descubrió que se debía a la codificación de la API por parte del compilador MASM32
A través de la comparación del desensamblaje, se descubrió que era debido a la codificación de la API por parte del compilador MASM32
A través de la comparación de desensamblaje, se encontró que el compilador MASM32 codificó la API
A través de la comparación de desensamblaje, se encontró que el compilador MASM32 codificó la API
Comparación de desensamblaje, descubrió que debido a que la codificación de las llamadas API por el compilador MASM32 es diferente de la codificación de las llamadas API por el compilador C, después de usar el programa de desmapping FreeLibrary o UnmapViewOfFile, el código en se hace referencia a la dirección de mapeo de IMAGEN [JMP DeleteFile] en la llamada a DeleteFile, lo que genera un error de ejecución de la memoria de lectura.
Análisis de errores
Cuando un programa normal realiza una llamada API, el compilador compilará la declaración de llamada API en varias instrucciones de pila de parámetros y luego la compilará en una declaración de llamada indirecta (aquí conocido como un compilador de Microsoft, el compilador de Borland usa JMP DWORD PTR [XXXXXXXXh]), su formato es el siguiente:
push arg1
push arg2
.. ....
llamar a dword ptr[XXXXXXXXh]
La dirección XXXXXXXXh se encuentra en la sección de importación de la imagen del programa.
Cuando el programa se carga y ejecuta, el cargador es responsable de agregar la dirección de la función API al programa;
1: Los programas compilados usando MASM32 tienen formato de llamada de función API:
Llamar capi;
......
......
......
capi :
jmp dword ptr[XXXXXXXXX]; La ventaja es que puede reducir el tamaño del código al llamar a la misma API varias veces, Dos: formato de llamada a función API de un programa compilado con C: Llame a dword ptr [XXXXXXXXXX] la dirección XXXXXXXX se almacena en la dirección real de la función API llamada; p> Es precisamente debido a los diferentes formatos de llamada de las funciones API anteriores que falla el programa de autoeliminación del programa compilado con MASM32. Porque después de llamar a UnmapViewOfFile, el código en la parte de instrucción jmp dword ptr [XXXXXXXXX] en el segmento de código se vuelve ilegible, y luego la ejecución de la API DeleteFile fallará y el programa generará un error. Por lo tanto, si usamos MASM32 para compilar este tipo de programa de autoeliminación, deberíamos cambiar la instrucción push DeleteFile a mov eax, DeleteFile y tomar jmp dword ptr[XXXXXXXXX; ] instrucción La dirección, el código de la máquina es FF25XXXXXXXXXX inc eax inc eax mov eax, dword ptr[eax] push dword ptr[eax] De esta manera, la dirección real de DeleteFile se puede colocar en la pila. Por supuesto, usar la API de adquisición dinámica también funciona, pero no es tan corto como este código. El siguiente es el código MASM32 que modifiqué [selfkill9x-nt.asm]: .386 .model flat, stdcall opción casemap: none p> incluir windows.inc p> incluir kernel32.inc incluir lib kernel32.lib .code Inicio: mov ebp, esp invocar GetModuleHandle, NULL; obtener su propio identificador de módulo mov ebx, esp invocar GetModuleHandle, NULL; identificador de módulo propio mov ebx, esp mov ebx, espmov ebx, eax invocar GetModuleFileName, ebx, ebp, MAX_PATH Obtener su propia ruta p> invocar CloseHandle, 4; cerrar el identificador de la IMAGEN que corresponde al archivo exe [codificado como 4] push 0; push ebp; Eliminar parámetros de archivo mov eax, ExitProcess inc eax inc eax mov eax , dword ptr[eax] push dword ptr[eax]; pushExitProcess push ebx; Parámetros de UnmapViewOfFile mov eax, DeleteFile inc eax inc eax mov eax, dword ptr[eax] push dword ptr[eax]; pushDeleteFile empujar ebx; parámetros de FreeLibrary mov eax, UnmapViewOfFile inc eax inc eax mov eax, dword ptr[eax] push dword ptr[eax]; pushUnmapViewOfFile push FreeLibrary ;No es necesario cambiar FreeLibrary porque la sección de código aún es legible cuando se llama ret endstart Inserción remota de subprocesos para autoeliminación p> La inserción remota de subprocesos ahora es ampliamente utilizada por troyanos y virus para protegerse y ocultarse. También podemos usarla para la autoeliminación de programas. El código para la inserción y autoeliminación remota de subprocesos es el siguiente: KREMOTE_CODE_START es igual a este byte Llamar a @F @@: pop ebx sub ebx, desplazamiento @B; reubicación del código de subproceso push 500 llamar [ ebx _lpselfkillSleep] ; Hibernar durante 0,5 segundos lea eax, [ebx offset _selfkillselfname] push eax llamar a [ebx _lpselfkillDeleteFile]; p> ret _lpselfkillSleep dd?; dirección codificada de Sleep _lpselfkillDeleteFile dd?; dirección codificada de DeleteFile _selfkillselfname :: El nombre del archivo propio del programa, en el programa principal Generar y escribir KREMOTE_CODE_END es igual a este byte KREMOTE_CODE_LENGTH es igual al desplazamiento KREMOTE_CODE_END - desplazamiento KREMOTE_CODE_START El programa principal usa GetProcAddress para obtener Sleep y DeleteFile y escribirlo arriba y usar GetModuleFileName para obtener su propia ruta _selfkillselfname para que la use el hilo remoto. Win9x maneja KERNEL32.DLL al crear código de subproceso remoto de la siguiente manera: Kernel32 db "KERNEL32.DLL", 0 SzCreateKernelThread db 'CreateKernelThread', 0 _RemoteCode9Xproc@_RmCodeStart, @_RmCodeLen lpThreadID local lpCreateKernelThread local hProcess local llama a GetModuleHandle, addr Kernel32 mov ebx, eax invocar GetProcAddress, ebx, offset szCreateKernelThread mov lpCreateKernelThread, eax Obtener la dirección de CreateKernelThread ; _findProcess es un procedimiento de función que encuentra el PID del proceso según el nombre del proceso, consulte [selfkill-R9x.asm] invocar _ findProcess, compensar Kernel32 buscar el proceso KERNEL32.DLL
invocar OpenProcess, PROCESS_ALL_ACCESS, TRUE, eax
mov hProcess, eax
invocar WriteProcessMemory, eax, 80001100h, @_RmCodeStart, @_RmCodeLen , NULL
.if eax
xor eax, eax
lea ecx, lpThreadID
push ecx
empujar eax
empujar eax
empujar 80001100h
empujar eax
empujar eax
empujar eax
push eax
llamar a lpCreateKernelThread; crear el hilo KERNEL32.DLL
.hilo .DLL
.endif
invokeCloseHandle, hProcess
.endif
ret
_RemoteCode9Xendp
El formato de llamada de esta función es el siguiente:
push KREMOTE_CODE_LENGTH MAX_PATH; longitud del código
push offset REMOTE_CODE; dirección del código
llamar a _RemoteCode9X
[Nota: no se usa aquí
invocar _ RemoteCode9X, compensa la función de llamada REMOTE_CODE, KREMOTE_CODE_LENGTH MAX_PATH
, porque cuando lo probé, descubrí que la llamada de invocación hará que KREMOTE_CODE_LENGTH MAX_PATH
¡El valor aumenta! ¿Quizás esto sea un error del compilador? ]
Primero use GetProcAddress en _RemoteCode9X para obtener la dirección de CreateKernelThread. Esta API se usa en KERNEL32.DLL [Los parámetros de CreateKernelThread son similares a los de CreateKernelThread, pero hay una diferencia: el parámetro lpStartAddress (el El hilo comienza a ejecutar la dirección) se encuentra en el proceso KERNEL32.DLL. ] Cree un hilo remoto en el proceso DLL. Primero se llama al proceso KERNEL32.DLL, luego se llama al procedimiento _findProcess para encontrar el PID del proceso KERNEL32.DLL, luego se abre el proceso con permisos completos y se usa WriteProcessMemory para escribir código en el espacio que comienza en 80001100h del KERNEL32 Proceso .DLL. La razón por la que elegí 80001100h es porque hay una gran sección de memoria no utilizada 00h, para no tener que ingresar al anillo 0 como lo hicieron los piratas informáticos chinos. ][]. ¡El hilo DLL se elimina solo! (En Win9x, consulte selfkill-R9x.asm para obtener el código completo de inserción y eliminación automática de subprocesos remotos).
En Win2K/XP, el código para crear un subproceso remoto es el siguiente:
; Se utiliza para insertar subprocesos remotos en el proceso explorer.exe
; Se utiliza para insertar subprocesos remotos en el proceso explorer.exe
; Proceso explorer.exe Hilo remoto.
proceso exe
szDesktopClassdb 'Progman', 0
szDesktopWindowdb 'Administrador de programas', 0
_RemoteCode2KXPproc @_RmCodeStart, @_RmCodeLen
local @hRmCodeMemory
local @hselfkillProcessID
local @hselfkillProcess
Busque la ventana del administrador de archivos y obtenga el ID del proceso, luego abra el proceso
invocar FindWindow, addr szDesktopClass, addr szDesktopWindow
lea ecx, @hselfkillProcessID
invocar GetWindowThreadProcessId, eax, ecx
invocar OpenProcess, PROCESS_CREATE_THREAD o PROCESS_VM_OPERATION o PROCESS_VM_WRITE, FALSE, @hselfkillProcessID
mov @hselfkillProcess, eax
Asigna espacio en el proceso y escribe código remoto, crea un hilo remoto
invocar VirtualAllocEx , @hselfkillProcess , NULL , @_RmCodeLen , MEM_COMMIT , PAGE_EXECUTE_READWRITE
.ifeax
mov@hRmCodeMemory,eax
invocar WriteProcessMemory,@hselfkillProcess,eax, @_RmCodeStart, @_RmCodeLen, NULL
xor eax, eax
invokeCreateRemoteThread, @hselfkillProcess, eax, eax, @hRmCodeMemory, eax, eax, eax
invokeCloseHandle , eax
.endif
invokeCloseHandle, @hselfkillProcess
return
_RemoteCode2KXPendp
El formato de llamada de este función ¡Igual que _RemoteCode9X!
La función anterior _RemoteCode2KXP primero llama a FindWindow y GetWindowThreadProcessId para obtener el PID del proceso explorer.exe, luego usa OpenProcess para abrir el proceso y permitir escribir en su memoria y crear subprocesos remotos, y luego llama a VirtualAllocEx y WriteProcessMemory para solicitar memoria en Escriba código en explorer.exe y, finalmente, use CreateRemoteThread para crear un hilo remoto y ejecutarlo.
(Para obtener el código completo de inserción remota de subprocesos y autoeliminación en Win2K/XP, consulte selfkill-Rnt.asm).
Autoeliminación de archivos por lotes
Sabemos eso en archivos por lotes Puede usar x para pasar la propia ruta al parámetro de lote 0 y usar del 0 para eliminar y lograr la autoeliminación del archivo por lotes.
Podemos aplicar esta técnica a nuestro propio programa y llamar al archivo por lotes para que se elimine para lograr el propósito de autoeliminación.
El archivo por lotes correspondiente generado es el siguiente:
@echo off
: selfkill
attrib -a -r -s - h "c:\selfkill-bat.exe"
del "c:\selfkill-bat.
Si existe "c:\selfkill-bat.exe"
Del "c:\selfkill-bat.exe"
Es bueno que tengas un archivo por lotes p>si existe "c:\selfkill-bat.exe" ve a selfkill
del 0
Lo modifiqué. Primero, usé @echo off para desactivar el mensaje de salida para que la ventana de DOS se cerrara automáticamente después de ejecutar el archivo por lotes. Luego usé attrib. para modificar los atributos del archivo para evitar que sea un atributo del sistema de solo lectura, oculto, no se puede eliminar mediante procesamiento por lotes, el nombre del programa debe estar entre comillas dobles para evitar que aparezcan espacios en la ruta [Ver selfkill-bat.asm para ver el código de muestra del uso del archivo por lotes para eliminar el programa en sí]
El archivo por lotes generado en el ejemplo se fija en "c:\Autoexce.bat" en lugar de generarse en el directorio actual para evitar la ruta del directorio contenga espacios, lo que provocará que el proceso por lotes no se ejecute y que el proceso por lotes no se genere. Esto es para evitar que la ruta del directorio contenga espacios, lo que provocará que el proceso por lotes no se ejecute, y para usar WinExec. ejecute el proceso por lotes de forma invisible sin mostrar la ventana de DOS
Autoeliminación en la máquina virtual de DOS
Este método fue proporcionado por mi amigo "Angel of Depression" (¡gracias!
#include lt;stdio.hgt;
int main(int argc, char *argv)
{
.unlink(argv[0]);
return 0;
}
Esta es una buena forma de autoeliminar en una máquina virtual DOS .
p>unlink Creo que los amigos que están familiarizados con el lenguaje C saben que se trata de eliminar el archivo especificado y usar TC2.0 para compilar el código anterior en un programa DOS de 16 bits. Después de ejecutarlo, verá si el programa. aparece después de que aparece una ventana de DOS. ¡Simplemente desapareció!
Reescribimos el programa anterior para aceptar parámetros:
#include lt; stdio.hgt
int main(int argc, char *argv[ ])
{
sleep(1); //hibernar durante 1 segundo.p>if(argc==2)
unlink(argv[1 ]) ; //eliminar el programa (parámetro uno)
unlink(argv[0]); //eliminarse
return 0;
}
A través del análisis de desmontaje y combinado con pruebas, encontramos el motivo de esta autoeliminación. El motivo de esta autoeliminación es que los programas en DOS pasan a través de la máquina virtual [subsistema MS-DOS de 16 bits] en Windows. (CPU NTVDM) ntvdm.exe se ejecuta en Win2000 y Winoa386.mod] se ejecuta en Win98. Cuando el programa DOS se ejecuta en la máquina virtual, también es equivalente a la ejecución interpretada (similar a la ejecución de scripts). leído en la memoria por la máquina virtual.
(Similar a la ejecución de un script), por lo que el sistema no lo protege al cargar un programa de DOS, por lo que puede eliminarse durante la ejecución. ¡Puede utilizar el siguiente método para verificar!
Utilice DEBUG para crear un programa COM de bucle infinito en DOS. El comando es el siguiente:
debug
-a
0B22. :0100 jmp 100
0B22:0102
-r cx
CX 0000
:.02
-n dos16 .com
-w
Escribe 00002 bytes
-q
Ejecutar el dos16.com generado generará un DOS ventana, elimine manualmente dos16.com debajo en esta ventana, ¿se realizó correctamente? 4301
0B22: 0108 xor cx, cx
0B22: 010A int 21
0B22: 010C mov ah, 41
0B22: 010E int 21
0B22:0110 cmp al, 5
0B22.0112 je 103
0B22:0114 lodsb
0B22:0115 o al, al
0B22:0117 jne 114
0B22:0119 cmp byte ptr [si], 0
0B22:011C jne 103
0B22:011E int 20
0B22:0120 db 'kill.com',0
0B22:0129 db 'selfkill.exe',0,0
0B22:0137
-r cx
CX 0000
:37
-n kill.com
-w
Escribe 00037 bytes
-q
El código anterior llama a la función 41 de la interrupción DOS INT 21 para eliminarse En cuanto a cómo una aplicación de Windows usa este método para eliminarse a sí misma, el código completo se puede encontrar en el archivo [selfkill-dos.asm]. ¡El método de llamada es el mismo que usar un programa por lotes para ejecutarlo de forma encubierta!
Scripts que se eliminan automáticamente
La proliferación de tiempos felices ha hecho que muchos de nosotros conozcamos los scripts VBS. Estos scripts se interpretan y ejecutan, por lo que se pueden eliminar en tiempo de ejecución, lo que significa que se pueden eliminar automáticamente. La eliminación de archivos de script no afectará la ejecución del código posterior.
Hagamos un experimento y guardemos el siguiente script como selfkill.vbs o selfkill.vbe:
Set fso = CreateObject("Scripting.FileSystemObject")
f = fso.WScript.ScriptName)
F = fso.WScript.ScriptName)
F = fso.WScript.ScriptName)