Vinnaren i pepparkakshustävlingen!
2024-07-12, 19:43
  #1
Medlem
Jag följer ett program i Ghidra och jag undrar vad som föregår med nedan händelsekedja:


Kod:
  int iVar2;
  uint uVar3;
   undefined4 *puVar6;
   undefined local_18;
  undefined auStack_17 [3];
  undefined4 *puStack_10;
 


  iVar2 = (*(code *)0x1b6966)();
  if (iVar2 == 0) {
    return 0xffffffff;
  }

puStack_10 = (undefined4 *)
               FUN_004bd173(-(uint)((int)(ZEXT48(auStack_17) * 4 >> 0x20) != 0) |
                            (uint)(ZEXT48(auStack_17) * 4));


    iStack_14 = iVar2 - (int)puStack_10;
    puVar6 = puStack_10;
 


Okej, PuStack_10 får ett värde av FUN_004bd173

Vi tittar på den funktionen:

Kod:
void __cdecl FUN_004bd173(uint param_1)

{
  operator_new(param_1);
  return;
}

Den returnerar Null. Så hur kan variablen användas senare?
Samt vad representerar enna hex 0xffffffff då den används lite var som helst.
Ghidra vill ha den till allt från ett superlångt decimaltal till L'\xffffffffff
__________________
Senast redigerad av Methos 2024-07-12 kl. 19:46.
Citera
2024-07-12, 19:56
  #2
Medlem
https://en.cppreference.com/w/cpp/me...w/operator_new

operator_new allokerar minne och returnerar en pekare, PuStack10 får ett implicit returnvärde (pekaren från operator_new) eftersom FUN inte explicit returnerar ett värde.

Sen vad den här parametern '-(uint)((int)(ZEXT48(auStack_17) * 4 >> 0x20) != 0) | (uint (ZEXT48(auStack_17) * 4)' är för något får någon annan ta.

Slutsatsen är att puStack10 kommer att vara en giltig pekare efter anropet förutsatt att allokeringen inte misslyckas, då blir den faktiskt null.
Citera
2024-07-12, 20:44
  #3
Medlem
Okej, så jag antar att det är en bit av dessa standardsaker som kompilatorn hittar på tillsammans med SCRT, UCRT etc.

Så om inte iVar2 får någon allokering från funktionen 0x1b6966 (som jag inte vet vad det är för funktion) så kommer den att få tilldelat adressen 0xffffffff.

Stack_1 får en pekare tilldelat till sig från operator_new().

Denna minnesadress hänger sedan med ner till en licenskontroll, så något nyttigt bör den användas till.
Citera
2024-07-16, 18:42
  #4
Medlem
Citat:
Ursprungligen postat av Emphorn
https://en.cppreference.com/w/cpp/me...w/operator_new
Sen vad den här parametern '-(uint)((int)(ZEXT48(auStack_17) * 4 >> 0x20) != 0) | (uint (ZEXT48(auStack_17) * 4)' är för något får någon annan ta.

Den koden kollar väl upp om bit 30 och 31 för det som sedan blir param1 är noll eller inte och sätter en etta om det inte är noll, och tar resten av värdet och shiftar den två steg åt vänster ( gånger fyra), och ett minustecken sätts framför det.

Jag gissar att det kortfattat är så.
__________________
Senast redigerad av JohanZzZ 2024-07-16 kl. 18:59.
Citera
2024-08-01, 05:20
  #5
Medlem
FUN_004bd173() returnerar inte NULL enligt ghidra, den returnerar ingenting.

Angående det långa aritmetiska uttrycket misstänker jag att det från början varit skrivet som:

FUN_004bd173((uintptr_t)auStack_17 >> 30 ? -1 : (uintptr_t)auStack_17 << 2);

Varför kompilatorn eller ghidra snurrat till det så är svårt att svara på, kan vara optimeringsskäl men troligare är att ghidras analys är konstig.

Jag gissar även att ghidras missar en vanlig optimering som kompilatorn gör när man returnerar returvärdet från en annan funktion (som FUN_004bd173() gör). Eftersom returvärdet redan ligger i retur-registret när operator_new() returnerar så behöver ju inte FUN_004bd173() flytta det dit. Ghidras analys tror att FUN_004bd173() har void som retur-signatur eftersom den aldrig ser att något läggs i retur-registret (det görs ju i operator_new()).

0xffffffff == -1, väldigt vanligt använt som felkod...
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in