PDA

Ver la Versión Completa : Porblema al obtener la MAC


QuiqueSalamanca
27-08-2014, 08:40:54
Buenos día a todos! cuanto tiempo sin pasar por aquí!

Os pongo en antecedentes! encontré hace tiempo una función por aquí que me devolvía la MAC y está genial pero tengo un ligero problemilla!
Dicha función la uso para el registro de mi aplicación yhace tiempo me paso en un cliente pero uno entre más de 300 pensaba que sería problema suyo y lo arreglé saltándome ésa validación pero debería meter un código que solo yo conozco y me mandaba un mail cada vez que lo hacía con varias características del ordenador, por si me hackeaban la aplicación.

Bien el problema es que me ha vuelto a pasar con otro cliente totalmente distinto, cada vez que apaga el ordenador la función me devuelve una MAC distinta y por tanto me des-registra la aplicación.

Os pongo la función para ver si me sabéis decir el por qué de éste problema porque yo llevo dos semanas volviéndome loco y no lo encuentro.


function GetPrimaryNicMacAddress: String;
type
TGUID = record
A, B: word;
D, M, S: word;
MAC: array[ 1..6 ] of byte;
end;
var
UuidCreateFunc: function(Var guid: TGUID): HResult; stdcall;
handle: THandle;
g: TGUID;
WinVer: _OSVersionInfoA;
i: integer;
// ErrCode : HResult;
begin
try
WinVer.dwOSVersionInfoSize := sizeof(WinVer); // Tamaño
getversionex(WinVer); // Obtiene info del Windows en uso
handle := LoadLibrary('RPCRT4.DLL'); // Obtiene el handle de la DLL
if WinVer.dwMajorVersion >= 5 then {Windows 2000 ó superior}
@UuidCreateFunc := GetProcAddress(Handle, 'UuidCreateSequential')
else // (Win98 o menor)
@UuidCreateFunc := GetProcAddress(Handle, 'UuidCreate');
UuidCreateFunc(g); // Obtiene la info
result := '';
for i := 1 to 6 do
Result := Result + IntToHex(g.MAC[ i ], 2); // Concatena la MAC Address
except
Result := ''; // Resultado nulo
end;
end;


Gracias de antemano!

Quique~

Casimiro Notevi
27-08-2014, 09:23:56
¿Has pensado que puede haber algún software instalado en ese cliente que cambie la mac?

QuiqueSalamanca
27-08-2014, 09:34:55
Hola Casimiro:

Si, he revisado que no tenga nada raro instalado solo veo antivirus y poco más ¿sabéis de algún programa especifico que te cambie la MAC cada vez que apagas el ordenador?

Gracias

Casimiro Notevi
27-08-2014, 09:39:21
Cuando lo apagas no, pero cuando lo enciendes supongo que sí, algunos virus, por ejemplo, he leido que hace eso.

QuiqueSalamanca
27-08-2014, 10:44:44
Cuando lo apagas no, pero cuando lo enciendes supongo que sí, algunos virus, por ejemplo, he leido que hace eso.

Hola Casimirio, si bueno me refería que en cuanto enciende es distinta.

Yo también pensé que es un virus o algo pero el cliente me asegura que no tiene ninguno que ha pasado el antivirus y no le ha detectado ninguna amenaza.

Me tocará hacer lo mismo que al otro pero me resulta raro que ya me ha pasado dos veces por eso comprobé la función y os pedí ayuda ya que no encuentro el posible fallo.

Gracias!

Casimiro Notevi
27-08-2014, 13:56:22
Si pasa en un equipo y los demás van bien, el problema es en ese equipo.
En cuanto a lo que diga el cliente, nunca jamás hago caso a eso.

duilioisola
27-08-2014, 17:18:38
Por lo que parece, ese procedimiento obtiene la MAC a partir de un GUID.
La GUID se generaba a partir de la MAC del ordenador y otras variables mas, para tener un identificador único en el mundo. Esto generó un problema de privacidad, ya que se podía identificar al ordenador que había generado ese valor.
Este problema de privacidad hizo que los GUID no se generaran con la MAC del ordenador.

http://es.wikipedia.org/wiki/Globally_unique_identifier
El algoritmo empleado para generar nuevos GUID ha sido ampliamente criticado. Al principio, la dirección MAC de la tarjeta de red del usuario se usaba como base para varios dígitos del identificador, lo que significa, por ejemplo, que un documento podía ayudar a averiguar qué ordenador lo había creado. Este agujero en la privacidad se utilizó para localizar al creador del gusano Melissa. Después de que esto se descubriera, Microsoft cambió el algoritmo, por lo que ya no se usa la dirección MAC.

La solución a esto es obtener la MAC de otra manera.
Yo lo hago de dos formas:
Busco la MAC de una direccion IP (para buscar la MAC del servidor de la base de datos)
Busco la MAC del ordenador. (esto puede traer algún problema si es un portatil y a veces se conecta por wifi y otras por ethernet)
Espero te sirva.


function MySendARP(const IPAddress: string): string;
var
DestIP : ULONG;
MacAddr : array [0..5] of byte;
MacAddrLen : ULONG;
SendArpResult : cardinal;
begin
/// Devuelve la direccion MAC de una direccion IP

DestIP := inet_addr(PAnsiChar(AnsiString(IPAddress)));
MacAddrLen := Length(MacAddr);
SendArpResult := SendARP(DestIP, 0, @MacAddr, @MacAddrLen);

if SendArpResult = NO_ERROR then
Result := Format('%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X',
[MacAddr[0], MacAddr[1], MacAddr[2],
MacAddr[3], MacAddr[4], MacAddr[5]])
else
Result := '';
end;

function DameIPLocal: string;
var
p : PHostEnt;
s : array[0..128] of char;
p2 : PChar;
wVersionRequested : word;
wsaData : TWSAData;
begin
/// Devuelve la direccion IP del ordenador

// Arranca la librería WinSock
try
wVersionRequested := MAKEWORD(1, 1);
WSAStartup(wVersionRequested, wsaData);

// Obtiene el nombre del PC
GetHostName(@s, 128);
p := GetHostByName(@s);

// Obtiene la dirección IP y libera la librería WinSock
p2 := iNet_ntoa(PInAddr(p^.h_addr_list^)^);
Result := Result + p2;
WSACleanup;
except
Result := '';
end;
end;

function DameMACLocal: string;
var // These are all needed for the WMI querying process
Locator : ISWbemLocator;
Services : ISWbemServices;
SObject : ISWbemObject;
ObjSet : ISWbemObjectSet;
SProp : ISWbemProperty;
Enum : IEnumVariant;
Value : cardinal;
TempObj : olevariant;
Valor : string;
Indice : integer;
IPAddress : string;
IPLocal : string;
begin
/// Devuelve la direccion MAC del adaptador de red que da la IP al ordenador

// Direccion de IP local del ordenador
IPLocal := DameIPLocal;
// Busco el indice del adaptador con la IP local
Indice := -1;
try
Locator := CoSWbemLocator.Create; // Create the Location object
// Connect to the WMI service, with the root\cimv2 namespace
Services := Locator.ConnectServer('', 'root\cimv2', '', '', '', '', 0, nil);
ObjSet := Services.ExecQuery('SELECT Index, IPAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True', 'WQL',
wbemFlagReturnImmediately and wbemFlagForwardOnly, nil);
Enum := (ObjSet._NewEnum) as IEnumVariant;
while (Enum.Next(1, TempObj, Value) = S_OK) do
begin
SObject := IUnknown(tempObj) as ISWBemObject;
SProp := SObject.Properties_.Item('IPAddress', 0);
if VarIsNull(SProp.Get_Value) then
Valor := ''
else
Valor := SProp.Get_Value[0];

IPAddress := Valor;

// Si la direccion del adaptador es la local, obtengo el indice
if (IPLocal = IPAddress) then
begin
SObject := IUnknown(tempObj) as ISWBemObject;
SProp := SObject.Properties_.Item('Index', 0);
if VarIsNull(SProp.Get_Value) then
Valor := ''
else
Valor := SProp.Get_Value;

Indice := StrToIntDef(Valor, 0);
end;
end;
except // Trap any exceptions (Not having WMI installed will cause one!)

end;

// Obtengo la MAC del adaptador con el indice obtenido
if (Indice >= 0) then
begin
try
Locator := CoSWbemLocator.Create; // Create the Location object
// Connect to the WMI service, with the root\cimv2 namespace
Services := Locator.ConnectServer('', 'root\cimv2', '', '', '', '', 0, nil);
ObjSet := Services.ExecQuery('SELECT MACAddress FROM Win32_NetworkAdapter WHERE Index = ' + IntToStr(Indice), 'WQL',
wbemFlagReturnImmediately and wbemFlagForwardOnly, nil);
Enum := (ObjSet._NewEnum) as IEnumVariant;
while (Enum.Next(1, TempObj, Value) = S_OK) do
begin
SObject := IUnknown(tempObj) as ISWBemObject;
SProp := SObject.Properties_.Item('MACAddress', 0);
if VarIsNull(SProp.Get_Value) then
Valor := ''
else
Valor := SProp.Get_Value;

Result := Valor;
end;
except // Trap any exceptions (Not having WMI installed will cause one!)
on Exception do
Result := 'ERR';
end;
end
else
Result := '';
end;

QuiqueSalamanca
29-08-2014, 10:21:29
Hola duilioisola:

Gracias por contestar, vaya fallo tuve en no darme cuenta sobre las GUID.

Leyendo tu código la función MySendARP devuelve la MAC de una IP por lo que ¿podría hacer esta llamada?

sMAC := MySendARP( DameIPLocal );

Puesto que yo en mi algoritmo de validación va cifrado en un fichero y un servidor de licencias en la cual puedo tener hasta 4 MACs diferentes registrando si es un portátil la MAC de la tarjeta de red wifi y la MAC de la tarjeta de red Ethernet ¿no?

Muchísimas gracias.

Casimiro, nunca me fio de ellos ni si quiera cuando tienen razón jeje.

Saludos,

nlsgarcia
30-08-2014, 20:08:01
QuiqueSalamanca,


...encontré hace tiempo una función...que me devolvía la MAC...dicha función la uso para el registro de mi aplicación...en un cliente...uno entre más de 300...cada vez que apaga el ordenador la función me devuelve una MAC distinta...

:rolleyes:

Revisa este código:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ActiveX, ComObj, WinSock;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

// Obtiene el MacAddress de una NIC Física
function GetMacAddress : String;

function GetIPAddress : String;
type
pu_long = ^u_long;
var
vTWSAData : TWSAData;
vPHostEnt : PHostEnt;
vTInAddr : TInAddr;
Buffer : Array[0..255] of Char;
begin
if WSAStartup($101,vTWSAData) <> 0 Then
Result := EmptyStr
else
begin
gethostname(Buffer,sizeof(Buffer));
vPHostEnt := gethostbyname(Buffer);
vTInAddr.S_addr := u_long(pu_long(vPHostEnt^.h_addr_list^)^);
Result := inet_ntoa(vTInAddr);
end;
WSACleanup;
end;

const
wbemFlagForwardOnly = $00000020;

var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet : OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
SQLWMI : String;
IPAddress : String;
NIC_IPAddress : String;
i : Integer;

begin

IPAddress := GetIPAddress;

if IPAddress = EmptyStr then
begin
Result := EmptyStr;
Exit;
end;

SQLWMI := 'Select IPAddress, MACAddress From Win32_NetworkAdapterConfiguration';

FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet := FWMIService.ExecQuery(SQLWMI,'WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;

while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin

if VarIsArray(FWbemObject.IPAddress) then
for i := VarArrayLowBound(FWbemObject.IPAddress,1) to
VarArrayHighBound(FWbemObject.IPAddress,1) do
NIC_IPAddress := NIC_IPAddress + ' ' + String(FWbemObject.IPAddress);

if Pos(IPAddress,NIC_IPAddress) > 0 then
begin
Result := FWbemObject.MACAddress;
FWbemObject := Unassigned;
Exit;
end
else
Result := EmptyStr;

FWbemObject := Unassigned;

end;

end;

// Muestra el MacAddress de una NIC Física
procedure TForm1.Button1Click(Sender: TObject);
var
MacAddress : String;
begin
MacAddress := GetMacAddress;
if MacAddress <> EmptyStr then
MessageDlg(MacAddress,mtInformation,[mbOK],0)
else
MessageDlg('No Existe una NIC Física Instalada en esta Máquina',mtInformation,[mbOK],0)
end;

end.

El código anterior en Delphi 7 sobre Windows 7 Professional x32, [I]permite obtener el MacAddress de una NIC Física por medio de su IP asignada la cual es obtenida de forma automática.

Nota: El código propuesto fue probado en una máquina que tiene una sola NIC Física instalada, funcionado correctamente según lo esperado, desconozco el comportamiento del mismo si es utilizado en una máquina que tengo dos o mas NIC, por ejemplo : Un Servidor.

Espero sea útil :)

Nelson.

nlsgarcia
01-09-2014, 01:26:09
QuiqueSalamanca,

Continuación del Msg #9

:rolleyes:

Revisa este código:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ActiveX, ComObj;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

// Obtiene el MacAddress de una NIC
function GetMacAddress(NetworkAdapter : String) : String;
const
wbemFlagForwardOnly = $00000020;

var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet : OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
SQLWMI : String;

begin

SQLWMI := 'Select MACAddress From Win32_NetworkAdapter Where NetConnectionID = '
+ QuotedStr(NetworkAdapter);

FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet := FWMIService.ExecQuery(SQLWMI,'WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;

if oEnum.Next(1, FWbemObject, iValue) = 0 then
begin
Result := String(FWbemObject.MACAddress);
FWbemObject := Unassigned;
end
else
Result := EmptyStr;

end;

// Muestra el MacAddress de una NIC
procedure TForm1.Button1Click(Sender: TObject);
var
MacAddress : String;
NetworkAdapter : String;
MsgApp : String;

begin

// El nombre del Network Adapter en Control Panel -> Network and Internet -> Network Connections
NetworkAdapter := 'Local Area Connection';

MacAddress := GetMacAddress(NetworkAdapter);

if MacAddress <> EmptyStr then
MessageDlg(MacAddress,mtInformation,[mbOK],0)
else
begin
MsgApp := Format('No Existe una NIC Asociada al Network Adapter : %s',[NetworkAdapter]);
MessageDlg(MsgApp,mtInformation,[mbOK],0)
end;

end;

end.

El código anterior en Delphi 7 sobre Windows 7 Professional x32, permite obtener el MacAddress de una NIC por medio del identificador de connección de red asociado, que se encuentra en : Control Panel -> Network and Internet -> Network Connections.

Espero sea útil :)

Nelson.