[C] Byte[4] naar Dword converten

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
Hallo iedereen,

Ik was aan het "Knokken" met Bytes en Dwords. Ik gebruik een Dword om naar een adres te verijzen.
Nu heb ik echter een address staan in een byte array. Dit is een adres die verwijst naar data die ik nodig heb.

Ik heb geprobeert op de volgende wijzen de bytes te converten naar een adres:

code:
1
2
3
4
5
6
7
DWORD getaddress(DWORD locatie,int size) {
    BYTE test[4] = {0x00};
    for(int i = 0; size > i; i++) {
        test[i] = *(BYTE*)(locatie + i);
    }
    return (DWORD)(test[3] << 24) | (test[2] << 16) | (test[1] << 8) | test[0];
}


Als ik het output naar een tekst documentje dan krijg ik het goeie adres.

code:
1
file << "Adres: " << (LPCWSTR)convertedad<< "\n"


Dit geeft bijvoorbeeld netjes:

code:
1
00112233


Alleen als ik dit adres ga gebruiken.. Dan werkt het niet meer. Type ik het adres zelf dan werkt het wel.
Ik heb hier echt al lang niet meer mee gewerkt, en ik zou ook echt niet weten wat het probleem kan zijn. Ziet iemand
toevallig het probleem?

Ik heb al een tijd gegoogled maar ik kan niet echt iets relevants vinden, en als je wat vind krijg je sites zoals deze:
http://www.experts-exchan...uages/CPP/Q_21582741.html

Ik heb zelf ook al verschilende creaties uitgeprobeert. Maar die willen ook niet. Zou iemand me een hint of zo kunnen geven?

Alvast bedankt!

[ Voor 4% gewijzigd door lauwsa op 08-11-2011 16:56 ]


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Wat bedoel je precies met
lauwsa schreef op dinsdag 08 november 2011 @ 16:55:

Alleen als ik dit adres ga gebruiken.. Dan werkt het niet meer. Type ik het adres zelf dan werkt het wel.
edit: wat me trouwens opvalt is dat je de endianness omdraait bij de conversie. Als het adres in LE is opgeslagen heb je na de conversie een BE representatie.

[ Voor 24% gewijzigd door EddoH op 08-11-2011 19:04 ]


Acties:
  • 0 Henk 'm!

  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
Bedankt voor je replay.
Ik bedoelde met het bovenstaande bijvoorbeeld dit:
Ik heb een Bytearray, hier is staat:

code:
1
BYTE test[4] = {0x33,0x22,0x11,0x00};


Deze wil ik converteren naar een adres. Dit moet worden: 0x00112233.

Als ik het op de bovenstaande methode omzet en het resultaat output naar een file:

code:
1
file << "Adres: " << (LPCWSTR)convertedad << "\n"


Dn krijg ik gewoon "00112233".

Gebruik ik deze vervolgens als adres ergens na toe. Dan loopt het programma vast. Gebruik ik een DWPRD waar ik:

code:
1
0x00112233


In stop dan loopt hij niet vast.
edit: wat me trouwens opvalt is dat je de endianness omdraait bij de conversie. Als het adres in LE is opgeslagen heb je na de conversie een BE representatie.
De gegevens worden als volgt opgeslagen: (BYTES)

code:
1
0x8B 0x0D    0x33 0x22 0x11 0x00


Dit is gelijk aan het adres:

code:
1
00112233


Ik heb me er nog nooit in verdiept waarom deze omgeswitcht worden. Is dat niet standaard bij x86?

Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Ik heb een Bytearray, hier is staat:

code:
1
BYTE test[4] = {0x33,0x22,0x11,0x00};


Deze wil ik converteren naar een adres. Dit moet worden: 0x00112233.
DWORD adres = *(DWORD *)test;
Als ik het op de bovenstaande methode omzet en het resultaat output naar een file:
code:
1
file << "Adres: " << (LPCWSTR)convertedad << "\n"


Dn krijg ik gewoon "00112233".
Wat is hier het type van convertedad? Een DWORD kun je niet zomaar naar LPCWSTR casten. Dus het is me niet duidelijk wat hier gebeurt. (Nog even daar gelaten dat de uitkomst toch minstens zou moeten beginnen met "Adres: ")
Ik heb me er nog nooit in verdiept waarom deze omgeswitcht worden. Is dat niet standaard bij x86?
Ja. Je specificeert alleen nergens dat het x86 code is. Deze specifieke operatie is een van de weinige waarbij het ertoe doet of het voor een Big- of een Little Endian systeem is.

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

lauwsa schreef op woensdag 09 november 2011 @ 11:18:

Gebruik ik deze vervolgens als adres ergens na toe. Dan loopt het programma vast. Gebruik ik een DWPRD waar ik:
Een adres ergens naar toe? Als in een geheugenlocatie? Hoe benader je die? Wat probeer je te doen. Post eens relevante code?
lauwsa schreef op woensdag 09 november 2011 @ 11:18:

Ik heb me er nog nooit in verdiept waarom deze omgeswitcht worden. Is dat niet standaard bij x86?
Bij x86 is het Little Endian: 'Little End First' (ezelsbrug).
Als je op een ' normale' manier type conversies doet hoef je je daar niet druk om te maken. Ik denk dan ook niet dat je helemaal op de goede weg zit.
Probeer eens wat duidelijker te maken wat je nu precies wilt bereiken.

Acties:
  • 0 Henk 'm!

  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
EddoH schreef op woensdag 09 november 2011 @ 11:58:
Een adres ergens naar toe? Als in een geheugenlocatie? Hoe benader je die? Wat probeer je te doen. Post eens relevante code?
Oke, neem als voorbeeld. Ik heb een applicatie. Ik wil hier een value in aan passen.
Ik wil bijvoorbeeld weten wat er gebeurt als de value 1 is, wat als de values 2 is etc.
Ik ben er eigelijk meer mee aan het hobien.

Stel je voor. Je hebt een waarde op de volgende locatie staan:

eendllbestand.dll op adres 0xABCDEF en het is een float.

Dan kan je *(PFLOAT)(dllhandle + 0xABCDEF) = 100.0f;

Nu verander je de waarde. Alleen als je constant het adres wilt gaan vinden is erg veel werk.
Dus ik dacht. Laat ik een soort byte searth maken die voor mij in de code het adres vind.

Ik heb het adres gevonden en dan krijg ik het in bytes terug. Deze bytes wil ik een DWORD van maken
zodat ik zoals hierboven naar de variable kan verwijzen. Alleen de convertatie gaat niet goed. Het lijkt net
alsof het adres er uit komt als "text" in plaats van een verwijzing.

Echt veel code kan ik eigelijk niet geven.

code:
1
2
3
4
5
6
7
DWORD getaddress(DWORD locatie,int size) {
    BYTE test[4] = {0x00};
    for(int i = 0; size > i; i++) {
        test[i] = *(BYTE*)(locatie + i);
    }
    return  (test[3] << 24) | (test[2] << 16) | (test[1] << 8) | test[0]
}


Hier komt dan een locatie binnen. Bvb "dllhandle + 0xAB12EF". Op de volgende bytes staat het adres geschreven.
Ik haal deze er dan uit en zet ze dan in test[].

Dus dan krijg je bvb:

code:
1
test[4] = {0xDD,0xCC,0xBB,0xAA};


Deze wil ik dan gebruiken om mee te verwijzen zoals hier boven:

code:
1
*(PFLOAT)(dllhandle + 0xABCDEF) = 100.0f;
Bij x86 is het Little Endian: 'Little End First' (ezelsbrug).
Als je op een ' normale' manier type conversies doet hoef je je daar niet druk om te maken. Ik denk dan ook niet dat je helemaal op de goede weg zit.
Sorry voor de onduidelijk heden. Ik denk dat ik idd helemaal fout bezig ben met de bytes te converten.
Mijzelf schreef op woensdag 09 november 2011 @ 11:33:
[...]

DWORD adres = *(DWORD *)test;
Dat wilt ook niet echt werken.
[...]
Wat is hier het type van convertedad? Een DWORD kun je niet zomaar naar LPCWSTR casten. Dus het is me niet duidelijk wat hier gebeurt. (Nog even daar gelaten dat de uitkomst toch minstens zou moeten beginnen met "Adres: ")
Daarom denk ik ook dat ik de converter fout gemaakt heb.

haha, "Adres: " had ik weg gelaten omdat dat niet echt relevant is naar mijn mening.
[...]
Ja. Je specificeert alleen nergens dat het x86 code is. Deze specifieke operatie is een van de weinige waarbij het ertoe doet of het voor een Big- of een Little Endian systeem is.
Sorry, zal het voortaan vermelden.

[ Voor 16% gewijzigd door lauwsa op 09-11-2011 12:46 ]


Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
lauwsa schreef op woensdag 09 november 2011 @ 12:43:
Echt veel code kan ik eigelijk niet geven.

code:
1
DWORD getaddress(DWORD locatie,int size)

Hier komt dan een locatie binnen. Bvb "dllhandle + 0xAB12EF". Op de volgende bytes staat het adres geschreven.
Locatie als in:
code:
1
DWORD locatie = dllhandle + 0xAB12EF
of als in:
code:
1
DWORD locatie = (DWORD)"dllhandle + 0xAB12EF"
En wat staat er dan op dat adres? Een float, of een pointer naar die float?

Heb je het gewenste adres ergens als string in je geheugen staan? Jouw output "Adres: 00112233" kan volgens mij alleen als 'convertedad' een pointer naar die string is.

[ Voor 5% gewijzigd door Mijzelf op 09-11-2011 13:06 ]


Acties:
  • 0 Henk 'm!

  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
Mijzelf schreef op woensdag 09 november 2011 @ 13:04:
[...]
Locatie als in:
code:
1
DWORD locatie = dllhandle + 0xAB12EF
of als in:
code:
1
DWORD locatie = (DWORD)"dllhandle + 0xAB12EF"
En wat staat er dan op dat adres? Een float, of een pointer naar die float?
Dat is de locatie in het geheugen waar de bytes staan die ik nodig heb om het adres te maken. Maar dat gedeelte is zo ver ik weet goed. Want de bytes heb ik gecontroleerd. En ze kloppen.

Dus: "DWORD locatie = dllhandle + 0xAB12EF"
Heb je het gewenste adres ergens als string in je geheugen staan? Jouw output "Adres: 00112233" kan volgens mij alleen als 'convertedad' een pointer naar die string is.
nee, heb ik nergens staan. Het adres verwijst bijvoorbeeld naar een float pointer. Deze verwijst dan weer naar de float zelf. Maar in dit geval heb ik al zat aan de float pointer.

Dus om kort te zeggen is dit het probleem:
Ik heb een array van bytes (bytes[4]). Deze komen uit het geheugen en vormen een adres. Dit adres wil ik kunnen gebruiken om er naar toe te verwijzen.

Dus:

code:
1
*pointernaardelocatie = getaddress(dllbestand + adres,grotevanhetadres);

Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
float *pfloat = (float *)*(INT_PTR *)(dlladres + offset);

Maar waarom zou je niet gewoon de variabele exporteren, of een functie exporteren waarmee je de variabele kunt manipuleren?

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

even over jouw code:
C:
1
2
3
4
5
6
7
DWORD getaddress(DWORD locatie,int size) {
    BYTE test[4] = {0x00};
    for(int i = 0; size > i; i++) {
        test[i] = *(BYTE*)(locatie + i);
    }
    return (DWORD)(test[3] << 24) | (test[2] << 16) | (test[1] << 8) | test[0];
}

eerste wat mij opvalt is dat je een size argument hebt, en als ik size < 0 danwel size > 4 invoer, ik je stack gesloopt hebt (buffer overflow)
tweede wat em opvalt is dat jij DWORD cast naar BYTE *, dat werkt alleen op 32bit systemen, op 64bit systemen heb je daar een crash (access violation)

Maar nu even constructief, wat ik begrijp is dat jij hebt een float in je DLL zitten, en je wilt daar het adres van gebruiken. Waarom gebruik je niet een float * ipv een dword? Daarnaast, een DLL gaat niet meer van locatie veranderen als hij geladen is, er zijn weinig redenen dat je met DLL-offsets wilt werken (buiten het reverse engineering/hacking van DLL's waarvan je de broncode niet hebt), gezien normaal gezien offsets afgehandeld worden door de linker (van de compiler) en de loader (van je OS).

Je kan gewoon een float* uitwisselen tussen DLL's (of EXE's) zolang je de betreffende DLL's niet ontlaad (ie, expliciete FreeLibrary), en mocht je dat wel doen, gaan offsets ook niet werken (om dezelfde reden, je DLL module gaat niet meer gepaged zijn na de FreeLibrary).

Ik denk dat je een veel te moeilijke oplossing zit te bouwen, kan je niet vertellen wat je wilt bereiken met het gebruik van die functie? hoe kom je aan de offset-adressen?

-niks-


Acties:
  • 0 Henk 'm!

  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
eerste wat mij opvalt is dat je een size argument hebt, en als ik size < 0 danwel size > 4 invoer, ik je stack gesloopt hebt (buffer overflow)
Bedankt, hier had ik niet op gelet. Ik zal er een cheak in bouwen.
het is een functie die vast in de code komt te staan om zo maar te zeggen. Dus een user kan er niks aan aanpassen. Alleen de programmeur. Maar het is idd wel beter om dit te controleren voor het geval dat.
tweede wat me opvalt is dat jij DWORD cast naar BYTE *, dat werkt alleen op 32bit systemen, op 64bit systemen heb je daar een crash (access violation)
Bedankt, dat wist ik niet. Dus wat ik nu heb gemaakt kan ik eigenlijk weg gooien.
Maar nu even constructief, wat ik begrijp is dat jij hebt een float in je DLL zitten,
Nee, deze zit in een andere DLL
er zijn weinig redenen dat je met DLL-offsets wilt werken
Ik ben idd met "reverse engineering" bezig.
kan je niet vertellen wat je wilt bereiken met het gebruik van die functie? hoe kom je aan de offset-adressen?
Deze funtie is er voor bedoelt om een array van bytes, dus bvb bytearray[4] om te zetten naar een adres. Om even in code te type:
code:
1
DWORD test = anderdllbestandhandle + 0x123456;

Waarvan 0x123456 uit de bytes moet ontstaan. die als volgt in elkaar zit: bytearray{0x56,0x34,0x12};


Even voor de duidelijkheid:
Ik wil in een ander dll bestand dingen aanpassen. Daarvan heb ik de "broncode niet" om zo maar te zeggen.
Ik heb het wel maar ik ben gewoon aan het hobbyen met reverse engineering.

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Okay, DWORD is wel een goed type voor een offset in een DLL (aangezien die niet groter dan 4GB kunnen worden), maar je moet niet vergeten dat 64 bit DLL's standaard geladen worden in het "high-end" van de "virtual address space" (ie, addressen > 0xFFFF000000000000 zo uit mijn hoofd), en als je dat in een DWORD stopt vallen de hoge 32 bit van het adres weg, en krijg je dus een "low-end" adres, en die zijn allemaal protected (kernel space), dus dan heb je AV's
Mocht je niet geven om 64 bit DLL's, dan kan je prima een DWORD gebruiken, maar als je ook 64 bit DLL's wilt gebruiken kan je beter kiezen voor een type als LONG_PTR.

Wat jouw code doet is volgens mij gewoon een 32bit pointer dereference, alleen dan met veel code :P (uitgaande van size == 4)
C:
1
2
3
4
5
//werkt alleen in 32bit proces
DWORD getaddress(DWORD locatie)
{
  return *(DWORD *)locatie;
}


Volgens mij is dit meer wat je zoekt
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
LONG_PTR getaddress(HMODULE base, BYTE offset[4])
{
  return (LONG_PTR)base + (LONG_PTR)*(DWORD *)offset;
}

//c++, geen c
float &interpretfloat(LONG_PTR address)
{
  return *(float *)address;
}

int main()
{
  BYTE offset[4] = { 0x56, 0x34, 0x12, 0x00 };
  HMODULE dll = LoadLibrary(...); //laad target DLL
  LONG_PTR address = getaddress(dll, offset);
  
  float before = interpretfloat(address);
  interpretfloat(address) = 100.0f;
}

-niks-


  • lauwsa
  • Registratie: Juli 2010
  • Laatst online: 10-09 20:43
Dat ziet er goed uit!
Heel erg bedankt voor jullie hulp.
Pagina: 1