View Full Version : [asm/C]chiamata con privilegi per leggere msr-SYSENTER?
GianFisa
09-06-2010, 20:45
Ciao, ho bisogno di leggere/scrivere un registro della cpu (intel) msr il 0x199, contentente moltiplicatore e v-core della cpu. ho trovato una funziona assembler "rdmsr" che dovrebbe fare al caso mio solo che và chiamata con i privilegi di kernel mode (livello 0), ho letto che la SYSENTER o un sistema call gate potrebbe fare al caso mio. ma nn ho capito come usarlo.
Qualche idea? mi andrebbe bene anche una funzione C o asm già fatta che legga i msr. ad esempio Crystal CPU (open source) fà quel lavoro ma nn riesco a nemmeno a ricompilare il programma o a estrarre le parti che mi servono perchè con VS dà un sacco di errori.
Grazie
ma grazie al piffero (scusa la schiettezza), non é che puoi entrare in kernel mode e uscire cosi come ti pare :D
invocare SYSENTER per te é inutile, su Windows serve solo ad invocare le chiamate di sistema, quindi non faresti altro che invocare qualche servizio del kernel.
non conosco questa istruzione rdmsr di cui parli e purtroppo al momento non ho a portata di mano i manuali dell'architettura x86, quindi non posso controllare, ma prima di impelagarti con la modalitá kernel controlla che quella sia effettivamente un'istruzione privilegiata.
anyway, diamo per scontato che lo sia, e che tu debba scrivere un programma che gira in kernel mode: in Windows i programmi che girano in kernel mode si chiamano drivers. forse tu hai bisogno di scrivere un driver per Windows, che é una cosa molto lontana dall'essere semplice, comunque per poter giudicare se questa soluzione é appropriata per quello che devi fare servono informazioni aggiuntive su cosa vuoi ottenere.
GianFisa
10-06-2010, 11:50
è privilegiata perchè compilandola su visual studio mi dà questo errore alla linea del comando rdmsr (file C++ con assembly inline):
Eccezione non gestita a 0x004113d5 in prova.exe: 0xC0000096: Privileged instruction.
Devo semplicemente leggere e scrivere in questi Model-Specific Registers con indirizzo noto...
Bel problema dunque, però sono credo che Cristal CPUID non utilizzi un driver per fare quelle operazioni..quindi magari c'è qualche exploit.
ho trovato questo che è più o meno quello che devo fare io ma mi dà dei problemi in compilazione:
http://www.computing.net/answers/programming/how-to-read-msr-or-physmem-in-win9x/15126.html
Bel problema dunque, però sono credo che Cristal CPUID non utilizzi un driver per fare quelle operazioni..quindi magari c'è qualche exploit. non conosco quel programma ma dal nome sembrerebbe usare l'istruzione assembly CPUID, appunto.
ho trovato questo che è più o meno quello che devo fare io ma mi dà dei problemi in compilazione:
http://www.computing.net/answers/programming/how-to-read-msr-or-physmem-in-win9x/15126.html ho letto molto velocemente ma li si parla di scrivere un VxD (Virtual Device Driver) per Windows 9x, che é il vecchio kernel; per giunta con MinGW, che non permette di farlo :rotfl:
scrivere un VxD oggi é perfettamente inutile, semmai dovresti scrivere un driver WDM, ma prima indaga sulla questione dell'istruzione CPUID.
GianFisa
11-06-2010, 14:08
Ho cercato info su questa istruzione CPUID, interessante però permette solo di leggere informazioni sulla cpu e non di scrivere su registri. invece cristal cpuid ha un modulo (provato e funzionante) che permette di inserire l'indirizzo del MSR e scriverci il valore che si vuole. ho trovato anche un altra applicazione open source che lo fà: performance inspector
http://perfinsp.sourceforge.net/ che ha un modulo che funziona su riga di comando..però anche lì si appoggia su varie dll è abbastanza complicato..
Comunque di sicuro usano qualche altra funzione...hai qualche indicazione da darmi su questi driver WDM? grazie!!
hai qualche indicazione da darmi su questi driver WDM? decisamente troppe. faccio un'altra proposta: se il registro che devi scrivere fa parte del contesto del thread corrente (cioé viene cambiato ad ogni thread switch) puoi usare questa API: http://msdn.microsoft.com/en-us/library/ms680632(VS.85).aspx
I model-specific registers (MSR) sono accessibili solo da kernel mode, ring0. Ma non è strettamente necessario utilizzare un driver per poter lavorarei in kernel mode.
Tuttavia stiamo parlando di tecniche molto avanzate, per cui l'utilizzo di un driver è fortemente consigliato.
Sì, le istruzioni sono rdmsr e wrmsr per leggere e scrivere questo specifico registro
Giusto per completezza, potresti utilizzare un'API non documentata.
ZwSystemDebugControl (http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Debug/NtSystemDebugControl.html) fa al caso tuo. Tecnicamente tra i comandi accettati di questa funzione ci sarebbero solo:
SysDbgQueryModuleInformation=1,
SysDbgQueryTraceInformation,
SysDbgSetTracepoint,
SysDbgSetSpecialCall,
SysDbgClearSpecialCalls,
SysDbgQuerySpecialCalls
In realtà ce ne sono molti altri, tra cui anche DebugSysReadMsr e DebugSysWriteMsr.
Per cui una chiamata da user mode a:
ZwSystemDebugControl(DebugSysReadMsr,&msr,sizeof(msr),NULL,0,NULL)
passandogli msr definito come MSR_STRUCT
typedef struct _MSR_STRUCT {
DWORD MsrNum;
DWORD NotUsed;
DWORD MsrLo;
DWORD MsrHi;
} MSR_STRUCT;
E mettendo su MsrNum il numero del registro da leggere/scrivere dovrebbe far e al caso tuo. MsrLo e MsrHi sono i valori (low e high 32 bit) che ti restituiscono il contenuto del registro, oppure li devi configurare tu se vai a scrivere il registro.
Occhio che questo "trucchetto", mentre funziona bene su Windows XP, potrebbe darti qualche noia su Windows Vista e Windows 7.
Ah, ovviamente richiede diritti di amministratore (richiede il SeDebugPrivilege).
Giusto per completezza, potresti utilizzare un'API non documentata. pessima idea: se non é documentata ci sará un motivo.
Occhio che questo "trucchetto", mentre funziona bene su Windows XP, potrebbe darti qualche noia su Windows Vista e Windows 7. ecco, appunto.
Ah, ovviamente richiede diritti di amministratore (richiede il SeDebugPrivilege). SeDebugPrivilege non é un "diritto di amministratore", é un privilegio che qualunque utente, anche non amministratore, puó avere.
GianFisa
13-06-2010, 17:01
Ciao, ho provato il metodo SetThreadContext Function ma non va bene perchè non mi permette di vedere i resistri msr ma solo i vari general eax...perchè sono fuori dal contesto del tread.
Poi ho provato il ZwSystemDebugControl come consigliato da eraser, anche aiutandomi con questo esempio: http://archives.neohapsis.com/archives/vulnwatch/2004-q1/att-0041/xploit_dbg.cpp
il codice che ho prodotto è questo (gira con codeblock compilatore gcc, con VS08 mi dà un errore in runtime), però non mi restituisce i valori in MsrLo e MsrHi, ho sbagliato qualcosa? potete aiutarmi? grazie mille a tutti.
#include <stdlib.h>
#include <windows.h>
#include <iostream>
using namespace std;
typedef struct _MSR_STRUCT {
DWORD MsrNum;
DWORD NotUsed;
DWORD MsrLo;
DWORD MsrHi;
} MSR_STRUCT;
typedef enum _DEBUG_CONTROL_CODE {
DebugSysReadIoSpace = 14,
DebugSysWriteIoSpace = 15,
DebugSysReadMsr = 16,
DebugSysWriteMsr = 17,
DebugSysReadBusData = 18,
DebugSysWriteBusData = 19,
} DEBUG_CONTROL_CODE;
typedef int NTSTATUS;
#define NTAPI __stdcall
typedef
NTSTATUS
(NTAPI *PZwSystemDebugControl)(
DEBUG_CONTROL_CODE ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
PZwSystemDebugControl ZwSystemDebugControl = NULL;
int main()
{
HMODULE hNtdll;
hNtdll = LoadLibrary("ntdll.dll");
ZwSystemDebugControl = (PZwSystemDebugControl)GetProcAddress(hNtdll, "ZwSystemDebugControl");
MSR_STRUCT msr;
msr.MsrNum=0x199;
msr.MsrHi=0;
msr.MsrLo=0;
ZwSystemDebugControl(DebugSysReadMsr,&msr,sizeof(msr),NULL,0,NULL);
cout<<msr.MsrLo;
cout<<msr.MsrHi;
system ("PAUSE");
return 0;
}
pessima idea: se non é documentata ci sará un motivo.
:asd:
Sì, Microsoft - come qualsiasi altra società - non dice tutto per ovvi motivi. Ciò non significa che non sia utilizzabile
ecco, appunto.
Sicuramente sai anche il perché, quindi è inutile che te lo spieghi e soprattutto sai perché è inutile e futile la tua affermazione
SeDebugPrivilege non é un "diritto di amministratore", é un privilegio che qualunque utente, anche non amministratore, puó avere.
Ho scritto a tirare via, visto che non cambia di molto la sostanza, a meno che tu non voglia consigliare di creare un account limitato, poi da amministratore configurargli il privilegio in questione e poi tornare sull'account appena creato. Direi che per una prova è alquanto sciocco. Ma forse avevi solo bisogno di pizzicare un po :asd:
Ciao, ho provato il metodo SetThreadContext Function ma non va bene perchè non mi permette di vedere i resistri msr ma solo i vari general eax...perchè sono fuori dal contesto del tread.
Poi ho provato il ZwSystemDebugControl come consigliato da eraser, anche aiutandomi con questo esempio: http://archives.neohapsis.com/archives/vulnwatch/2004-q1/att-0041/xploit_dbg.cpp
il codice che ho prodotto è questo (gira con codeblock compilatore gcc, con VS08 mi dà un errore in runtime), però non mi restituisce i valori in MsrLo e MsrHi, ho sbagliato qualcosa? potete aiutarmi? grazie mille a tutti.
Il codice è grosso modo corretto, ma ti sei dimenticato di abilitare il privilegio SE_DEBUG_PRIVILEGE.
Puoi farlo attraverso l'API AdjustTokenPrivileges http://msdn.microsoft.com/en-us/library/aa375202(VS.85).aspx che è documentata.
(Oppure molto più semplicemente tramite l'API non ufficialmente documentata RtlAdjustPrivilege, in maniera molto più rapida e semplice. Sempre che siano tutti d'accordo :D)
GianFisa
14-06-2010, 00:59
ok funziona! grazie mille per l'aiuto, posto il codice completo nel caso servisse a qualcun altro, ciao
#include <stdlib.h>
#include <windows.h>
#include <iostream>
using namespace std;
typedef int NTSTATUS;
#define NTAPI __stdcall
typedef NTSTATUS (WINAPI *pFnRtlAdjustPrivilege)(
ULONG Privilege,
BOOLEAN Enable,
BOOLEAN CurrentThread,
PBOOLEAN Enabled
);
pFnRtlAdjustPrivilege RtlAdjustPrivilege;
typedef struct _MSR_STRUCT {
DWORD MsrNum;
DWORD NotUsed;
DWORD MsrLo;
DWORD MsrHi;
} MSR_STRUCT;
typedef enum _DEBUG_CONTROL_CODE {
DebugSysReadIoSpace = 14,
DebugSysWriteIoSpace = 15,
DebugSysReadMsr = 16,
DebugSysWriteMsr = 17,
DebugSysReadBusData = 18,
DebugSysWriteBusData = 19,
} DEBUG_CONTROL_CODE;
typedef
NTSTATUS
(NTAPI *PZwSystemDebugControl)(
DEBUG_CONTROL_CODE ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
PZwSystemDebugControl ZwSystemDebugControl = NULL;
int main()
{
//setto i privilegi di debug
RtlAdjustPrivilege = (pFnRtlAdjustPrivilege)GetProcAddress(LoadLibrary("Ntdll.dll"), "RtlAdjustPrivilege");
BOOLEAN bEnabled = FALSE;
RtlAdjustPrivilege(20, 1, 0, &bEnabled);;
HMODULE hNtdll;
hNtdll = LoadLibrary("ntdll.dll");
ZwSystemDebugControl = (PZwSystemDebugControl)GetProcAddress(hNtdll, "ZwSystemDebugControl");
MSR_STRUCT msr;
//MSR_STRUCT msr_o;
msr.MsrNum=0x199;
msr.MsrHi=0;
msr.MsrLo=2599;
ZwSystemDebugControl(DebugSysReadMsr,&msr,sizeof(msr),NULL,0,NULL);
//ZwSystemDebugControl(DebugSysWriteMsr,&msr,sizeof(msr),NULL,0,NULL);
cout<<"alti "<<msr.MsrHi;
cout<<"bassi"<<msr.MsrLo;
system ("PAUSE");
return 0;
}
ok funziona! grazie mille per l'aiuto, posto il codice completo nel caso servisse a qualcun altro, ciao
Sono contento :) Ottimo!
Mi raccomando, non è un modo standard di funzionare e funziona senza problemi solo su Windows XP (su Windows Vista e Windows 7 ci sono alcuni problemi dovuti ad una configurazione interna leggermente differente). Per cui se devi fare qualcosa di affidabile e distribuirlo su larga scala io punterei più ad un driver che esegua le istruzioni privilegiate rdmsr e wrmsr.
Se invece è solo per test o per qualcosa di interno, allora può andare :)
Ciao! :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.