1

I want to know what command line arguments are accepted by an application. I have decompiled it using Ghidra and found a function called ParseCommandLine, but I don't understand what it is doing. I expected it to compare each option to some strings to determine what it is, but it looks like gibberish.

How can I figure out what the below code is doing? Or is there a better way to figure out what command line options are available?

Additional context: I'm using a Macbook, and the application is the first Jackbox Party Pack. I want to see if I can launch one of the games directly without opening their game selector.

Code:

/* WARNING: Could not reconcile some variable overlaps */
/* Scaleform::Platform::Args::ParseCommandLine(int, char**) */

undefined8 __thiscall ParseCommandLine(Args *this,int param_1,char **param_2)

{
  int *piVar1;
  uint uVar2;
  ulong uVar3;
  ulong uVar4;
  char *pcVar5;
  long lVar6;
  bool bVar7;
  ulong *puVar8;
  long *plVar9;
  byte bVar10;
  int iVar11;
  char *pcVar12;
  undefined *puVar13;
  undefined *puVar14;
  ulong uVar15;
  undefined8 *puVar16;
  RefCountImpl *this_00;
  long lVar17;
  long *plVar18;
  undefined8 uVar19;
  long *plVar20;
  uint **ppuVar21;
  char *pcVar22;
  char **ppcVar23;
  char **ppcVar24;
  long lVar25;
  ulong local_78;
  char **local_70;
  int local_68;
  uint local_64;
  char **local_60;
  char **local_58;
  char **local_50;
  char **local_48;
  ulong local_40;
  long *local_38;

  local_40 = (ulong)(param_1 - 1U);
  local_38 = (long *)this;
  if (param_1 - 1U != 0 && 0 < param_1) {
    pcVar12 = PTR_vtable_10094f650 + 0x10;
    puVar13 = PTR_vtable_10094f710 + 0x10;
    puVar14 = PTR_vtable_10094f648 + 0x10;
    local_68 = 0;
    do {
      ppcVar24 = param_2 + 1;
      pcVar22 = param_2[1];
      if (*pcVar22 == '-') {
        ppcVar23 = (char **)(pcVar22 + 1);
        local_60 = param_2;
        iVar11 = _prompt_string(ppcVar23,"psn_",4);
        param_2 = ppcVar24;
        if (iVar11 != 0) {
          local_50 = ppcVar23;
          String((String *)&local_78,(char *)ppcVar23);
          local_58 = (char **)((ulong)local_58 & 0xffffffff00000000 | (ulong)(uint)param_1);
          if (((long *)this)[6] != 0) {
            uVar15 = BernsteinHashFunctionCIS
                               ((void *)((long)(ulong *)(local_78 & 0xfffffffffffffffc) + 0xc),
                                *(ulong *)(local_78 & 0xfffffffffffffffc) & 0x7fffffffffffffff,
                                0x1505);
            lVar17 = ((long *)this)[6];
            uVar15 = uVar15 & *(ulong *)(lVar17 + 8);
            if ((*(long *)(lVar17 + 0x10 + uVar15 * 0x28) != -2) &&
               (*(ulong *)(lVar17 + 0x18 + uVar15 * 0x28) == uVar15)) {
              puVar8 = (ulong *)(lVar17 + 0x10 + uVar15 * 0x28);
              local_48 = (char **)((local_78 & 0xfffffffffffffffc) + 0xc);
              uVar3 = puVar8[1];
              uVar4 = uVar15;
              while ((uVar3 != uVar15 ||
                     (iVar11 = _default_RAND_meth((puVar8[2] & 0xfffffffffffffffc) + 0xc,local_48),
                     iVar11 != 0))) {
                uVar4 = *puVar8;
                if (uVar4 == 0xffffffffffffffff) goto LAB_1006b2610;
                puVar8 = (ulong *)(lVar17 + 0x10 + uVar4 * 0x28);
                uVar3 = puVar8[1];
              }
              if (-1 < (long)uVar4) {
                lVar25 = *(long *)(lVar17 + 0x28 + uVar4 * 0x28);
                local_48 = *(char ***)(lVar17 + 0x30 + uVar4 * 0x28);
                bVar7 = true;
                goto LAB_1006b261b;
              }
            }
          }
LAB_1006b2610:
          lVar25 = 0;
          local_48 = (char **)0x0;
          bVar7 = false;
LAB_1006b261b:
          LOCK();
          piVar1 = (int *)((local_78 & 0xfffffffffffffffc) + 8);
          *piVar1 = *piVar1 + -1;
          if (*piVar1 == 0) {
            (**(code **)(*pGlobalHeap + 0x68))();
          }
          if (!bVar7) {
            __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                      (*(undefined8 *)__ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE
                       ,"Unknown option : %s \n",local_50);
          }
          uVar2 = *(uint *)(*local_38 + 0x10 + lVar25 * 0x28);
          bVar10 = (byte)uVar2 & 0xf;
          if (bVar10 == 1) {
            local_40._0_4_ = (int)local_58 - 2;
            if ((uint)local_40 == 0 || SCARRY4((int)local_58,-2) != (int)(uint)local_40 < 0) {
              __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                        (*(undefined8 *)
                          __ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE,
                         "Option \"%s\" must have arguments.\n",local_50);
              this = (Args *)local_38;
            }
            else {
              lVar17 = CreateValue(local_60[2],uVar2);
              plVar9 = local_38;
              ppcVar24 = local_48;
              plVar20 = (long *)(local_38[3] + (long)local_48 * 8);
              this_00 = *(RefCountImpl **)(local_38[3] + (long)local_48 * 8);
              plVar18 = plVar20;
              if (this_00 != (RefCountImpl *)0x0) {
                Release(this_00);
                plVar18 = (long *)((long)ppcVar24 * 8 + plVar9[3]);
              }
              param_2 = local_60 + 2;
              *plVar20 = lVar17;
              this = (Args *)local_38;
              if (*plVar18 == 0) {
                __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                          (*(undefined8 *)
                            __ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE,
                           "Cannot parse parameter for \"%s\" \n",local_50);
                this = (Args *)local_38;
              }
            }
          }
          else {
            if (bVar10 == 4) {
              if ((int)local_58 < 3) {
                uVar19 = *(undefined8 *)
                          __ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE;
LAB_1006b29ad:
                __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                          (uVar19);
                this = (Args *)local_38;
              }
              else {
                local_58 = (char **)(**(code **)(*pGlobalHeap + 0x50))(pGlobalHeap,0x28,0);
                *(uint *)(local_58 + 1) = 1;
                *(undefined *)((long)local_58 + 0xc) = 0;
                *local_58 = pcVar12;
                local_58[4] = (char *)0x0;
                local_58[3] = (char *)0x0;
                local_58[2] = (char *)0x0;
                if ((1 < (int)local_40) && (pcVar22 = local_60[2], *pcVar22 != '-')) {
                  local_70 = local_58 + 2;
                  ppcVar23 = local_60 + 2;
                  local_64 = uVar2;
                  do {
                    local_50 = ppcVar23;
                    this_00 = (RefCountImpl *)CreateValue(pcVar22,local_64);
                    ppcVar24 = local_58;
                    ResizeNoConstruct((
                                       ArrayDataBase<Scaleform--Ptr<Scaleform--Platform--ArgValue>,Scaleform--AllocatorGH<Scaleform--Ptr<Scaleform--Platform--ArgValue>,2>,Scaleform--ArrayDefaultPolicy>
                                       *)local_70,local_70,(ulong)(local_58[3] + 1));
                    pcVar22 = ppcVar24[2];
                    pcVar5 = ppcVar24[3];
                    if (this_00 == (RefCountImpl *)0x0) {
                      *(undefined8 *)(pcVar22 + (long)pcVar5 * 8 + -8) = 0;
                    }
                    else {
                      AddRef(this_00);
                      *(RefCountImpl **)(pcVar22 + (long)pcVar5 * 8 + -8) = this_00;
                      Release(this_00);
                    }
                    ppcVar24 = local_50;
                    if ((int)((uint)local_40 + -2) < 1) {
                      ppuVar21 = (uint **)((long)local_48 * 8 + local_38[3]);
                      local_40 = (ulong)((uint)local_40 - 1);
                      goto LAB_1006b2b76;
                    }
                    pcVar22 = local_50[1];
                    ppcVar23 = local_50 + 1;
                    local_40 = (ulong)((uint)local_40 - 1);
                  } while (*pcVar22 != '-');
                }
                ppuVar21 = (uint **)((long)local_48 * 8 + local_38[3]);
                if (local_58 == (char **)0x0) {
                  bVar7 = true;
                }
                else {
LAB_1006b2b76:
                  AddRef((RefCountImpl *)local_58);
                  bVar7 = false;
                }
                if (*ppuVar21 != (uint *)0x0) {
                  Release((RefCountImpl *)*ppuVar21);
                }
                *(char ***)ppuVar21 = local_58;
                param_2 = ppcVar24;
                this = (Args *)local_38;
                if (!bVar7) {
                  Release((RefCountImpl *)local_58);
                  this = (Args *)local_38;
                }
              }
            }
            else {
              this = (Args *)local_38;
              if (bVar10 == 2) {
                if ((uVar2 & 0xf0) != 0x10) {
                  uVar19 = *(undefined8 *)
                            __ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE;
                  goto LAB_1006b29ad;
                }
                puVar16 = (undefined8 *)(**(code **)(*pGlobalHeap + 0x50))(pGlobalHeap,0x20,0);
                *(undefined4 *)(puVar16 + 1) = 1;
                *(undefined *)((long)puVar16 + 0xc) = 0;
                *(undefined **)puVar16 = puVar13;
                String((String *)(puVar16 + 2),"");
                *(undefined *)((long)puVar16 + 0xc) = 1;
                *(undefined **)puVar16 = puVar14;
                *(undefined *)(puVar16 + 3) = 1;
                operator=((String *)(puVar16 + 2),"true");
                *(undefined *)((long)puVar16 + 0xc) = 1;
                lVar17 = local_38[3];
                this_00 = *(RefCountImpl **)(lVar17 + (long)local_48 * 8);
                if (this_00 != (RefCountImpl *)0x0) {
                  Release(this_00);
                }
                *(undefined8 **)(lVar17 + (long)local_48 * 8) = puVar16;
                this = (Args *)local_38;
              }
            }
          }
        }
      }
      else {
        uVar15 = (ulong)(ushort)local_68;
        if ((ulong)((long *)this)[8] < uVar15 || ((long *)this)[8] == uVar15) {
          __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                    (*(undefined8 *)__ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE,
                     "Unknown positional value \"%s\"\n",pcVar22);
        }
        else {
          ppcVar23 = (char **)(uVar15 * 0x10);
          uVar2 = *(uint *)(*(long *)this + 0x10 +
                           *(long *)(((long *)this)[7] + (long)ppcVar23) * 0x28);
          if ((uVar2 & 0xf) == 4) {
            local_58 = (char **)(*(long *)this + 0x10 +
                                *(long *)(((long *)this)[7] + (long)ppcVar23) * 0x28);
            local_70 = ppcVar23;
            local_60 = (char **)(**(code **)(*pGlobalHeap + 0x50))(pGlobalHeap,0x28,0);
            *(undefined4 *)(local_60 + 1) = 1;
            *(undefined *)((long)local_60 + 0xc) = 0;
            *local_60 = pcVar12;
            local_48 = local_60 + 2;
            local_60[4] = (char *)0x0;
            local_60[3] = (char *)0x0;
            local_60[2] = (char *)0x0;
            do {
              if (**ppcVar24 == '-') break;
              uVar15 = (ulong)((int)local_40 - 1);
              local_50 = ppcVar24;
              this_00 = (RefCountImpl *)CreateValue(*ppcVar24,*(uint *)local_58);
              ppcVar24 = local_60;
              ResizeNoConstruct((
                                 ArrayDataBase<Scaleform--Ptr<Scaleform--Platform--ArgValue>,Scaleform--AllocatorGH<Scaleform--Ptr<Scaleform--Platform--ArgValue>,2>,Scaleform--ArrayDefaultPolicy>
                                 *)local_48,local_48,(ulong)(local_60[3] + 1));
              pcVar22 = ppcVar24[2];
              pcVar5 = ppcVar24[3];
              local_40 = uVar15;
              if (this_00 == (RefCountImpl *)0x0) {
                *(undefined8 *)(pcVar22 + (long)pcVar5 * 8 + -8) = 0;
              }
              else {
                AddRef(this_00);
                *(RefCountImpl **)(pcVar22 + (long)pcVar5 * 8 + -8) = this_00;
                Release(this_00);
              }
              ppcVar24 = local_50 + 1;
            } while (0 < (int)(uint)local_40);
            lVar17 = local_38[3];
            lVar25 = *(long *)(local_38[7] + 8 + (long)local_70);
            if (local_60 != (char **)0x0) {
              AddRef((RefCountImpl *)local_60);
            }
            this_00 = *(RefCountImpl **)(lVar17 + lVar25 * 8);
            if (this_00 != (RefCountImpl *)0x0) {
              Release(this_00);
            }
            local_40._0_4_ = (uint)local_40 + 1;
            local_40 = (ulong)(uint)local_40;
            ppcVar24 = ppcVar24 + -1;
            *(char ***)(lVar17 + lVar25 * 8) = local_60;
            this = (Args *)local_38;
            if (local_60 != (char **)0x0) {
              Release((RefCountImpl *)local_60);
              this = (Args *)local_38;
            }
          }
          else {
            uVar19 = CreateValue(pcVar22,uVar2);
            lVar17 = ((long *)this)[3];
            lVar25 = *(long *)(((long *)this)[7] + 8 + (long)ppcVar23);
            this_00 = *(RefCountImpl **)(lVar17 + lVar25 * 8);
            if (this_00 != (RefCountImpl *)0x0) {
              Release(this_00);
            }
            *(undefined8 *)(lVar17 + lVar25 * 8) = uVar19;
            this = (Args *)local_38;
          }
        }
        local_68 = local_68 + 1;
        param_2 = ppcVar24;
      }
      local_40 = (ulong)((uint)local_40 - 1);
      param_1 = (uint)local_40;
    } while ((uint)local_40 - 1 != 0 && 0 < (int)(uint)local_40);
  }
  lVar17 = ((long *)this)[6];
  if (lVar17 == 0) {
    return 0;
  }
  plVar20 = (long *)(lVar17 + 0x10);
  uVar15 = 0;
  do {
    if (*plVar20 != -2) break;
    uVar15 = uVar15 + 1;
    plVar20 = plVar20 + 5;
  } while (uVar15 < *(ulong *)(lVar17 + 8) || uVar15 == *(ulong *)(lVar17 + 8));
  lVar17 = ((long *)this)[6];
  do {
    do {
      if (lVar17 == 0) {
        return 0;
      }
      if (*(long *)(lVar17 + 8) < (long)uVar15) {
        return 0;
      }
      if (*(long *)(((long *)this)[3] + *(long *)(lVar17 + 0x30 + uVar15 * 0x28) * 8) == 0) {
        lVar25 = *(long *)(lVar17 + 0x28 + uVar15 * 0x28);
        lVar6 = *(long *)this;
        uVar2 = *(uint *)(lVar6 + 0x10 + lVar25 * 0x28);
        if ((uVar2 & 0x100) != 0) {
          __ZN9Scaleform6Render2GLL53ShaderDesc_FS_GLSL150_FInstancedYUVACxformAcEAlphaInvE
                    (*(undefined8 *)__ZN9Scaleform6Render2GLL34ShaderDesc_FS_GLSL150_FBatchYUVMulE,
                     "Mandatory option \"%s\" or \"%s\" is not found \n",
                     *(undefined8 *)(lVar6 + lVar25 * 0x28),
                     *(undefined8 *)(lVar6 + 8 + lVar25 * 0x28));
          return 2;
        }
        uVar19 = CreateValue(*(char **)(lVar6 + 0x18 + lVar25 * 0x28),uVar2);
        lVar17 = *(long *)(lVar17 + 0x30 + uVar15 * 0x28);
        lVar25 = ((long *)this)[3];
        this_00 = *(RefCountImpl **)(lVar25 + lVar17 * 8);
        if (this_00 != (RefCountImpl *)0x0) {
          Release(this_00);
        }
        *(undefined8 *)(lVar25 + lVar17 * 8) = uVar19;
        lVar17 = local_38[6];
        this = (Args *)local_38;
      }
    } while ((long)*(ulong *)(lVar17 + 8) < (long)uVar15);
    plVar20 = (long *)(lVar17 + 0x38 + uVar15 * 0x28);
    do {
      uVar15 = uVar15 + 1;
      if (*(ulong *)(lVar17 + 8) < uVar15) break;
      lVar25 = *plVar20;
      plVar20 = plVar20 + 5;
    } while (lVar25 == -2);
  } while( true );
}
  • You can rename variables, write comments, etc. Usually it's not fast.. – Olvin Roght Jan 22 at 8:41
5

1) you demangle the function names for these which are called within the function

2) you learn the arguments of these functions and apply the names to local variables which are passed as arguments to the functions

3) you learn the structures and apply them to stack variables, so that you can name more stack variables which are assigned to the structure fields

4) you learn what is returned from the function and name the error code variable or return value variable

5) you learn how arguments of the function are processed

6) you name the rest of the local variables

7) you look at the whole function again and learn what it actually does

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.