Red de conocimiento informático - Consumibles informáticos - Montaje e inversión de accionamientos

Montaje e inversión de accionamientos

Para una persona que escribe programas con frecuencia, escribir controladores no es una tarea difícil. Porque hay muchos ya preparados en línea.

Código, para implementar una determinada función, solo Ctrl+C y Ctrl+V pueden resolver el problema. ¿Pero puedo agregarlo después de escribir el controlador?

Cargar el kernel es otra cuestión, y si se puede almacenar en el disco duro de otra persona es otra cuestión.

Debido a que muchos software antivirus (especialmente aquellos sin contenido técnico como 360) eliminan directamente archivos con el sufijo sys,

Ni siquiera tuve la oportunidad de llamar a NtLoadDriver. Para software general, proporcione una declaración que explique la solución.

Olvídate de soluciones. Pero en el caso de los programas maliciosos, no se puede dar una explicación. Muchos autores de malware encontraron otra manera.

Usar controladores firmados digitalmente y escritos por grandes empresas para hacer cosas malas.

Algunas personas dicen, ¿cómo se puede utilizar un controlador fabricado por una gran empresa para hacer cosas malas? De hecho, esto es fácil de entender.

Muchos software de seguridad o optimización del sistema, incluso software que no tiene nada que ver con el sistema (como Thunder), vienen con sus propios controladores.

Estas unidades son universales. El internauta Q_lai_a_qu dijo en el blog: "ComputerZ.sys.........nada.

El reverso es el controlador de Master Lu. Descubrí que este controlador es completamente funcional y no ha sido verificado. por la persona que llama. Puede leer y escribir Msr.

Registro, también puede usar instrucciones de entrada y salida para leer y escribir puertos, ¡la longitud de datos char/short/long está completa! Esta es

mi opinión personal, adivine la credibilidad usted mismo. Permítanme comenzar con un ejemplo más creíble: una vez hubo un virus que usaba 360.

Software antivirus que elimina archivos antirk.dll (busque en Google "360 antirk.dll", se sorprenderá.

AntiRK.dll no es un controlador, pero sí lo es). también es ilegal su uso). Los virus que dañan el software antivirus son un juego de niños.

De hecho, ¡el uso de algunos controladores también puede dañar el hardware! Recientemente, estaba jugando con el hardware de mi computadora portátil y un internauta de la Asociación de Amistad me la recomendó.

Software recomendado: SetFSB, ThrottleStop, NvFlash, WinFlash. Están modificando la frecuencia externa de la CPU, configurando el multiplicador de la CPU (el voltaje de la CPU es ajustable), leyendo y escribiendo el BIOS de gráficos y leyendo y escribiendo el software del BIOS de la placa base. Para resumir sus características en una frase,

Todos soportan NT x86/x64, y los drivers tienen firmas digitales oficiales (especialmente los dos últimos, que tienen firmas digitales de NVIDIA y ASUS respectivamente).

Lo más importante es que su conductor no esté cubierto y la persona que llama no esté verificada.

Si utiliza estos controladores y un poco de conocimiento de ingeniería inversa, puede crear un virus destructivo (lo siguiente es un extracto de mi publicación en el foro de programación de Purple Water

Crystal):

1.SetFSB puede ajustar la frecuencia externa del procesador. Si ajusta directamente la frecuencia externa a 600MHz, la computadora se apagará instantáneamente, lo que puede

dañar la CPU o la placa base;

2. La CPU no está bloqueada (multiplicador), si ajusta directamente el multiplicador a 31,

la computadora se apagará instantáneamente, lo que puede dañar la CPU o la placa base; ThrottleStop también puede ajustar el voltaje del núcleo de la CPU.

Ajustar el voltaje del núcleo de la CPU a 3 V puede quemar directamente la CPU o incluso la placa base.

3. NvFlash, WinFlash y otro software pueden leer y escribir directamente el BIOS (gráficos); BIOS de la tarjeta y BIOS de la placa base), podemos

Escribir todos los ceros en el BIOS;

4. Si es un virus, primero escriba el BIOS de la tarjeta gráfica y la BIOS de la placa base defectuosos y luego grabe. la tarjeta gráfica y la CPU ajustando el voltaje.

(Puede dañarse junto con la placa base);

Solución

Se puede ver que el daño de no verificar el controlador de la llamada es grande. . Recientemente la Academia me asignó un

software que requiere un controlador (el controlador estará firmado digitalmente). Para evitar que ocurra la tragedia anterior, decidí escribir formalmente.

Antes de conducir, descubre cómo evitar que tu conductor sea explotado maliciosamente. He hecho esta pregunta antes en el foro de programación de amatista.

Los internautas tienen varias respuestas a esta pregunta, pero se pueden dividir aproximadamente en tres categorías: la primera categoría es la verificación de información, como las aplicaciones.

Envía mensajes al controlador para verificar que son "tuyos"; el segundo tipo es la protección de shell, como agregar a controladores y aplicaciones.

Sobre un caparazón extremadamente duro, la parte de comunicación está cifrada por VMP (similar a lo que hace XueTr; otros proponen aplicaciones híbridas, síntesis

prácticas combinadas de categoría 1 y 2);

Estas tres ideas parecen buenas, pero creo que todas están equivocadas. El primero: otros solo necesitan revertir todos los controladores.

El segundo tipo: aunque la protección VMP y las carcasas protectoras dificultan el agrietamiento, no lo hacen imposible. Y

No me gusta que VMP y los shells protectores reduzcan la eficiencia de la ejecución del programa. Lo peor de todo es que el software antivirus añade un shell (incluso).

Incluso se ha informado que proyectos como UPX y VMP están envenenados, lo que no vale la pena perder. Entonces se me ocurrió una tercera idea: comprobar las características de la persona que llama. Si es así, la declaración de función se ejecuta; de lo contrario, no se ejecuta. ¿Cómo verifico la firma de una persona que llama? Mucha gente quiere

usar CRC32 o MD5. No es que no pueda usarlos, pero tengo mis propias ideas. Mi idea surgió de

Diseñar un conjunto de algoritmos de verificación, las reglas son las siguientes:

1. Obtener el proceso electrónico del llamante

2. EPROCESS obtiene la ruta del archivo de la persona que llama.

3. Obtenga todo el contenido del archivo de la persona que llama y colóquelo en un búfer de matriz de bytes.

4. Suma y resta todos los elementos en buff (fb1+fb2-fb3...) para obtener y1.

5. Exclusivamente O todos los elementos en buff (0 XOR fb1 XOR fb2 XOR fb3...) para obtener y2.

Compara y1 e y2 con los valores calculados. Si son iguales, ejecuta el código de función; si no son iguales, no son iguales.

Ejecutar código de función

Utilice PsGetCurrentProcess() para obtener directamente el EPROCESS de la persona que llama y obtener la ruta del archivo de la persona que llama.

La ruta es más problemática. Puede usar el código que compré de un experto antes (ha sido encapsulado en una función para facilitar la llamada):

//Obtenga la ruta completa. del proceso según e proceso.

VOID getfullpathbyprocess(ULONG e proceso, PCHAR ProcessImageName)

{

Objeto ULONG;

PFILE _ OBJECT FileObject

Ruta del archivo UNICODE_STRING;

UNICODE _ STRING DosName

Reorganización de la cadena;

FileObject = NULL

Ruta del archivo. Buffer = NULL

Ruta del archivo.

longitud = 0;

* proceso imagenname = 0;

//e proceso-& gt; objeto de sección offset _)

if(MmIsAddressValid ((PULONG)(e proceso+desplazamiento _ objeto de sección)))

{

objeto =(*(PULONG)(e proceso+desplazamiento _ objeto de sección)); p>

//KD print(("[GetProcessFileName]objeto de sección:0x % x \ n ",objeto));

if(MmIsAddressValid((PULONG)((ULONG)objeto +0x 014)))

{

objeto = *(PULONG)((ULONG)objeto+0x 014);

//KD print(( "[ GetProcessFileName]Segmento:0x % x \ n ", objeto));

if(MmIsAddressValid((PULONG)((ULONG)objeto+0x 0)))

{

objeto = *(PULONG)((ULONG _ PTR)objeto+0x 0);

//KD print(("[GetProcessFileName]

ControlAera :0x %x\n ", objeto));

if(MmIsAddressValid((PULONG)((ULONG)objeto+0x 024)))

{

objeto = *(PULONG)((ULONG)objeto+0x 024);

if(NtBuildNumber & gt;= 6000)objeto =((ULONG)objeto &

0x fffffff 8);

//KD print(("[GetProcessFileName]

FilePointer:0x%x\n ", objeto));

}

Otros

Devolver;

}

Otros

Devolver;

}

Otro

Devolver;

}

Otro

Devolver;

FileObject = (PFILE_OBJECT) objeto;

Ruta del archivo. buffer = ExAllocatePool(grupo de páginas, 0x 200);

Ruta del archivo. Longitud máxima = 0x200

//KD print(("[GetProcessFileName]

Puntero de archivo:%wZ\n ", & puntero de archivo-> nombre de archivo));

ObReferenceObjectByPointer((PV oid)objeto de archivo, 0, NULL, modo kernel);

RtlVolumeDeviceToDosName(objeto de archivo-& gt; objeto de dispositivo. nombre de dos);

RtlCopyUnicodeString(& ruta del archivo.

dos nombre);

rtlapendunicodestringtostring(& ruta de archivo.objeto de archivo->nombre de archivo);

ObDereferenceObject(objeto de archivo);

rtlunicodestringtansigning (& asignar y allocate.FilePath, TRUE);

if (Registering. Longitud>= 216)

{

memcpy(ProcessImageName, AnsiString. buffer, 0x 100 u)

*(proceso imagename+215)= 0

}

Otro

{

memcpy; (ProcessImageName, AnsiString. Buffer, asignación. Longitud);

ProcessImageName[AnsiString. longitud]= 0;

}

rtlfreeansigning(&ansi ssing);

ExFreePool(DosName.buffer);

ExFreePool (ruta del archivo. buffer);

}

El código anterior requiere tres códigos físicos, a saber, NtBuildNumber (número de versión del sistema) y EPROCESS.

El desplazamiento del elemento SectionObject y del elemento UniqueProcessId. El sistema operativo que probé fue Windows 2003. Entonces

Lo definí en el código de la siguiente manera:

# define offset _ objeto de sección 0x 124

# define offset _ UniqueProcessId 0x 94

ULONG NtBuildNumber = 3790

Verifique la firma después de obtener la ruta del proceso. Debido a que el proceso se ha explicado claramente, el código se proporciona directamente:

VOID CalcChar(puni code _ STRING logFileUnicodeString, LONG *XorChar, LONG

*AnSChar)

{

OBJECT_ATTRIBUTES atributos del objeto;

IO _ STATUS _ BLOCK iostatus

Procesando hfile

NTSTATUS ntStatus

File_Standard_Information;

Puchal Puffer;

ULONG i=0, y1=0, y2 = 0;

//Atributos del objeto de inicialización

InitializeObjectAttributes(& Atributos de objeto,

logFileUnicodeString,

OBJ no distingue entre mayúsculas y minúsculas, // distingue entre mayúsculas y minúsculas.

Vacío,

NULL);

//Crear archivo

ntStatus = ZwCreateFile(& hfile,

GENERIC_READ

& atributo de objeto,

&iostatus,

null,

file_attribute_normal,

archivo compartido leído,

FILE_OPEN, // se crea incluso si existe en este archivo.

FILE_SYNC_IO_NON-ALERT,

NULL,

0 );

IF(!NT_SUCCESS(ntStatus))

{

dprintf("¡El archivo no existe! \n ");

Regresar

}

//Leer; longitud del archivo

ntStatus = ZwQueryInformationFile(hfile,

& ampiostatus,

& ampfsi,

sizeof(archivo Información estándar),

Información estándar del archivo);

dprintf ("El programa quiere leer %d bytes\n ", fsi. endo ffile . quad part); /Asignar búfer para archivos de lectura

pBuffer =(PUCHAR)ExAllocatePool(grupo paginado,

(long)fsi.endo ffile.quad part

/ /Leer archivo

ZwReadFile(hfile, NULL,

Vacío, vacío,

& ampiostatus,

p buffer,

(long)fsi. Cuatro partes,

NULL, NULL);

dprintf("El programa leyó % d bytes\n ",iostatus.info);

//Cálculo XOR

for(I = 0; i<iostatus.info;i++)

y1=y1^(long)(*(pbuffer+i ));

* xor char = y 1;

//Operaciones de suma y resta

for(I = 0;i<iostatus.info;i++)

{

if (i%2==0)

y2 = y2+(LONG )(*(p buffer+I));

Otros

y2 = y2-(LONG)(*(p buffer+I));

}

* AnSChar = y2

//Cerrar el identificador del archivo

zw close(hfile);

//Liberar el búfer

ex free pool(p buffer);

}

Se llamará a continuación. Necesitamos escribir una función VerifyCaller, que tiene dos valores.

Lo que se solidifica en el conductor son dos valores característicos de las personas que llaman legalmente.

Para facilitar el cálculo de estos dos valores característicos, escribí especialmente una aplicación. El código principal es el siguiente:

Opción explícita

Función privada ReadFile (ByVal strFileName como cadena). , opcional ByVal

lngStartPos As Long = 1, opcional ByVallngFileSize As Long =-1)As Byte()

Dim FilNum As Long

FilNum = FreeFile

Abra strFileName del archivo binario en formato #FilNum

Si lngFileSize = -1, entonces

ReDim ReadFile(LOF(FilNum)- lngStartPos)

Otro

ReDim ReadFile(lngFileSize-1)

Terminará si...

Obtiene #FilNum, lngStartPos, ReadFile

Cerrar #FilNum

Función final

Función privada WriteFile(ByVal strFileName es una cadena, bytData() es un byte,

Opcional ByVal lngStartPos As Long =-1, ByVal opcional sobrescribir como booleano =

Verdadero)

Ir a erx en caso de error

Atenuar FilNum mientras

FilNum = FreeFile

Si OverWrite = True y Dir(strFileName)<>""Entonces

Elimina strFileName

Terminará si...

Abra el strFileName del archivo binario en formato #FilNum

Si lngStartPos = -1, entonces

ponga #FilNum, LOF(FilNum) + 1, bytData

Otro

Will #FilNum, lngStartPos, bytData

Terminará si...

Cerrar #FilNum

p>

erx:

Función final

Subcomando privado 1_Click()

Dim buff() es byte, I es largo, y es largo, ub es largo

text1.text es el nombre del archivo

buff = ReadFile(Text1. Texto, 1, -1)

ub = UBound(buff)

Calcular carácter XOR

y = 0

Para i = 0 a ub

y = y XOR buffer(I)

luego

text2. Texto = CLng(y)

Actividades múltiples

Cálculo de caracteres adicionales/sub

y = 0

Para i = 0 a ub

Si i módulo 2 = 0, entonces

y = y + CLng(buff(i))

Otros

y = y - CLng(buff(i))

Terminará si...

Entonces

SMS 3. Texto = CLng(y)

Conector final

Subform_Load() privado

i.

Icon = LoadPicture(" ")

Conector final

El código VerifyCaller en el controlador es el siguiente:

Llamante de verificación larga (no válido)

{

PEPROCESS cur_ep

char cur_PP[260];

char*nt_cur_pp

ANSI _ STRING asCur _ pp

UNICODE _ STRING usCur _ pp

LONG xorc, ansc

cur _ EP = PsGetCurrentProcess();

getfullpathbyprocess((ULONG)cur_EP,cur_PP);

//Agrega el símbolo \ \ antes del nombre del archivo.

nt_cur_pp=cs("\\\\ ", cur _ PP);

DbgPrint("%s ", nt _ cur _ PP); >rtlinitansigning(& asCur_pp, nt_cur_PP);

rtlansistringunicodestring(&us cur_PP & asCur_pp, TRUE);

DbgPrint("% wZ ",&us cur_PP);

karchar(&us cur_PP&xorc &ansc);

dbg print(" xor char: % LD; AnSChar: %ld ", xorc, ansc); Es un código de característica precalculado por un programa legal y debe solidificarse en el controlador.

if(xorc == 186 & ampansc==136176)

Devuelve 1;

Otro

Devuelve 0; >

}

Antes de ejecutar cada función de la función DispatchIoctl, llame a VerifyCaller() para verificar la persona que llama:

Switch (uIoControlCode)

{

Caso IOCTL_VERIFY:

{

dbg print("[mi controlador]DispatchIoctl-IOCTL _ VERIFY ");

if(VerifyCaller ()==1)

dbg print("¡El código de función [mi controlador]{ IOCTL _ VERIFY } se está ejecutando ahora!");

Otros

dbg print("[mi conductor]{ IOCTL _ VERIFY } ¡Eres una persona que llama ilegalmente!");

status = status_success;

Roto;

}

//Omitido a continuación

}

Prueba heurística

3. Primero, separe las personas que llaman legales y las ilegales (use eXeScope). para parchear a la persona que llama legítimamente a voluntad,

por ejemplo, para eliminar la información de la versión del programa) y copiar el controlador a la máquina virtual.

4. Cargue el controlador con un llamador legítimo y ejecútelo.

5. Cargue el controlador con un llamador ilegal y ejecútelo.

6. Compare el resultado de los dos anteriores en DbgView.

Cuando la persona que llama es legal:

Cuando la persona que llama es ilegal:

Escríbalo al final

Después de escribir este artículo, Debo reiterar que sólo si el conductor porta una firma digital oficial se podrá realizar la llamada.

El código es útil.

¿Por qué dices eso? Porque otros no pueden parchear al conductor con una firma digital formal (una vez

Cuando el conductor es parcheado, la firma no será válida, como una mujer destrozada, sin valor. Aunque esta metáfora es común, pero muy

apropiado). Sin un controlador de firma, no hay valor de uso. Incluso si otros quieren usarlo, simplemente tírelo al conductor.

En IDA sale todo el código.