Advertisement
brightprogrammer

xvm-decompile-state-1

Sep 18th, 2021
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.71 KB | None | 0 0
  1. #include <stddef.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdint.h>
  6.  
  7. typedef struct{
  8.     // first 48 bytes of memory (0x00 -> 0x30)
  9.     uint64_t uint64arr[6];
  10.  
  11.     // from 48 to 60 bytes (0x30 -> 0x40)
  12.     uint32_t uint32arr[4];
  13.  
  14.     // last 4 bytes (0x40 -> 0x44)
  15.     uint8_t uint8arr[4];
  16. } StructOne;
  17.  
  18. StructOne* structOneCtor(void){
  19.     StructOne* pStructOne = (StructOne*)malloc(sizeof(StructOne));
  20.  
  21.     memset((void*)pStructOne, 0, 0x40);
  22.  
  23.     // then we setting some selected indices in this array
  24.     pStructOne->uint32arr[1] = 0x13371000;
  25.     pStructOne->uint32arr[2] = 0xcafe3ffc;
  26.     pStructOne->uint32arr[3] = 0xcafe3ffc;
  27.  
  28.     pStructOne->uint8arr[0] = 4;
  29.  
  30.     return pStructOne;
  31. }
  32.  
  33. typedef struct SectionHeader{
  34.     char* pName;                    // 0x00
  35.     uint8_t* pByteCode;             // 0x08
  36.     uint32_t size;                  // 0x10
  37.     uint32_t bcd2;                  // 0x14
  38.     uint32_t f18;                   // 0x18
  39.     uint32_t bcd3;                  // 0x1c
  40.     uint32_t currentReadAddress;                   // 0x20
  41.     uint32_t f24;                   // 0x24
  42.     struct SectionHeader* pNext;    // 0x28
  43. } SectionHeader;                    // total = 0x30
  44.  
  45. SectionHeader* sectionHeaderCtor(){
  46.     SectionHeader* pSectionHeader = (SectionHeader*)(malloc(sizeof(SectionHeader)));
  47.    
  48.     pSectionHeader->pName = 0;
  49.     pSectionHeader->pByteCode = 0;
  50.     pSectionHeader->size = 0;
  51.     pSectionHeader->bcd2 = 0;
  52.     pSectionHeader->f18 = 0;
  53.     pSectionHeader->bcd3 = 1;
  54.     pSectionHeader->currentReadAddress = 0;
  55.     pSectionHeader->pNext = NULL;
  56.  
  57.     return pSectionHeader;
  58. }
  59.  
  60. typedef struct{
  61.     // this is actually a linked list
  62.     struct SectionHeader *pSectionHeader;
  63.     uint32_t* arrUint32;
  64. }StructThree;
  65.  
  66. typedef struct{
  67.     uint32_t* magicValue;
  68.     uint64_t* arr1;
  69.     StructThree *pStructThree;
  70.     FILE* pFile;
  71. } XVMHeader;
  72.  
  73. XVMHeader* xvmHeaderCtor(){
  74.     XVMHeader* pXVMHeader = (XVMHeader*)(malloc(sizeof(XVMHeader)));
  75.    
  76.     pXVMHeader->magicValue = (uint32_t*)(malloc(sizeof(uint32_t) * 5));
  77.     pXVMHeader->magicValue[0] = 0x036d7678;
  78.     pXVMHeader->magicValue[0] = 0x13371000;
  79.     pXVMHeader->magicValue[0] = 0;
  80.     pXVMHeader->magicValue[0] = 0;
  81.     pXVMHeader->magicValue[0] = 0;
  82.  
  83.     pXVMHeader->arr1 = (uint64_t*)(malloc(sizeof(uint64_t) * 2));
  84.     if(pXVMHeader->arr1 != NULL){
  85.         pXVMHeader->arr1[0] = 0;
  86.         pXVMHeader->arr1[1] = 0;
  87.     }
  88.  
  89.     pXVMHeader->pStructThree = (StructThree*)(malloc(sizeof(StructThree)));
  90.     pXVMHeader->pStructThree->pSectionHeader = NULL;
  91.     pXVMHeader->pStructThree->arrUint32 = NULL;
  92.  
  93.     pXVMHeader->pFile = NULL;
  94.  
  95.     return pXVMHeader;
  96. }
  97.  
  98. int32_t closeFileIfOpened(XVMHeader* pXVMHeader){
  99.     if(pXVMHeader == NULL) return -1;
  100.     if(pXVMHeader->pFile == NULL) return 0;
  101.     fclose(pXVMHeader->pFile);
  102.     pXVMHeader->pFile = NULL;
  103.     return 0;
  104. }
  105.  
  106. // this is fcn_46f4
  107. int32_t checkIfFileIsOpen(XVMHeader* pXVMHeader, const char* filename){
  108.     // var_8h is pStructThree
  109.     // var_10h is pSectionHeaderName
  110.  
  111.     if(pXVMHeader == NULL) return -1;
  112.  
  113.     // check if file is already open
  114.     if(pXVMHeader->pFile != NULL){
  115.         closeFileIfOpened(pXVMHeader);
  116.     }
  117.  
  118.     // open file
  119.     pXVMHeader->pFile = fopen(filename, "r");
  120.  
  121.     // check if file was opened or not
  122.     if(pXVMHeader->pFile == NULL){
  123.         return -1;
  124.     }
  125.  
  126.     return 0;
  127. }
  128.  
  129. // renamed it
  130. int32_t checkValidXVMByteCode(XVMHeader* pXVMHeader){
  131.     if(pXVMHeader->magicValue == NULL){
  132.         return -1;
  133.     }
  134.  
  135.     // seek to beginning of file
  136.     fseek(pXVMHeader->pFile, 0, 0);
  137.  
  138.     // read magic values from file
  139.     fread(pXVMHeader->magicValue+0, 1, 4, pXVMHeader->pFile);
  140.     fread(pXVMHeader->magicValue+4, 1, 4, pXVMHeader->pFile);
  141.     fread(pXVMHeader->magicValue+8, 1, 4, pXVMHeader->pFile);
  142.     fread(pXVMHeader->magicValue+12, 1, 4, pXVMHeader->pFile);
  143.     fread(pXVMHeader->magicValue+16, 1, 4, pXVMHeader->pFile);
  144.  
  145.     // check if valid xvm
  146.     // if you convert "03 6d 76 78" into ascii, you will get "?mvx"
  147.     if(pXVMHeader->magicValue[0] != 0x36d7678){
  148.         fwrite("[\x1b[31m-\x1b[0m] Corrupted Bytecode\n", 1, 0x20, stderr);
  149.         exit(-1);
  150.     }
  151.  
  152.     return 0;
  153. }
  154.  
  155. // renamed from fcn_4ff1
  156. void copySectionHeader(SectionHeader* pSectionHeader, char* pSectionHeaderName, uint32_t size, uint32_t bcd2, uint32_t bcd3){
  157.     if((size & 0xfff) != 0){
  158.         size = ((size >> 0xc) + 1) << 0xc;
  159.     }
  160.  
  161.     if(size <= 0x10000) size = 0x10000;
  162.  
  163.     if(pSectionHeaderName != NULL){
  164.         if(pSectionHeader->pName != NULL){
  165.             // pName is actually a char*, see below in "else" block
  166.             pSectionHeader->pName = (uint64_t)realloc((void*)pSectionHeader->pName, 0x20);
  167.             strncpy((char*)pSectionHeader->pName, pSectionHeaderName, 0x20);
  168.         }else{
  169.             // wow, so pSectionHeader is actually the section header itself
  170.             // the first field is section name
  171.             // and the last field points to next section header
  172.             // we will change this on our next refactor
  173.             pSectionHeader->pName = (uint64_t)(strdup(pSectionHeaderName));
  174.         }
  175.     }
  176.  
  177.     pSectionHeader->size = size;
  178.     pSectionHeader->bcd2 = bcd2;
  179.     pSectionHeader->bcd3 = bcd3;
  180.     pSectionHeader->currentReadAddress = 0;
  181.     pSectionHeader->f18 = 0;
  182.     // I think size is the size of this section header
  183.     pSectionHeader->pByteCode = (uint64_t)realloc((void*)pSectionHeader->pByteCode, size);
  184.     pSectionHeader->pNext = NULL;
  185. }
  186.  
  187. // reamed from fcn_5315
  188. SectionHeader* makeSectionHeader(StructThree* pStructThree, char* pSectionHeaderName, uint32_t size, uint32_t bcd2, uint32_t bcd3){
  189.     if((size & 0xfff) != 0){
  190.         size = ((size >> 0xc) + 1) << 0xc;
  191.     }
  192.  
  193.     if(size >= 0x10000){
  194.         size = 0x10000;
  195.     }
  196.  
  197.     if(size == 0){
  198.         size = 0x1000;
  199.     }
  200.  
  201.     if(((uint64_t)size + (uint64_t)bcd2) > 0x100000000){
  202.         return 0;
  203.     }else{
  204.         if(pStructThree == NULL){
  205.             return 0;
  206.         }else{
  207.             if(pStructThree->pSectionHeader == NULL){
  208.                 pStructThree->pSectionHeader = sectionHeaderCtor();
  209.  
  210.                 pStructThree->arrUint32[0] = pStructThree->arrUint32[0] + 1;
  211.                 copySectionHeader(pStructThree->pSectionHeader, pSectionHeaderName, size, bcd2, bcd3);
  212.  
  213.                 return pStructThree->pSectionHeader;
  214.             }else{
  215.                 SectionHeader* var_18h = pStructThree->pSectionHeader;
  216.                 SectionHeader* var_10h = 0;
  217.  
  218.                 if(size + bcd2 < var_18h->bcd2){
  219.                     SectionHeader* var_8h = sectionHeaderCtor();
  220.  
  221.                     pStructThree->arrUint32[0] = pStructThree->arrUint32[0] + 1;
  222.                     copySectionHeader(var_8h, pSectionHeaderName, size, bcd2, bcd3);
  223.                    
  224.                     var_8h->pNext = pStructThree->pSectionHeader;
  225.                     pStructThree->pSectionHeader = var_8h;
  226.  
  227.                     return var_8h;
  228.                 }else{
  229.                     while(var_18h != NULL){
  230.                         if((bcd2 >= var_18h->bcd2) && (bcd2 < var_18h->bcd2 + var_18h->size)){
  231.                             if((size != var_18h->size) && (var_18h->pNext != 0)){
  232.                                 if((size + var_18h->bcd2) < var_18h->pNext->bcd2){
  233.                                     var_10h->pByteCode = (uint64_t)realloc((void*)(var_18h->pByteCode), size);
  234.                                 }else{
  235.                                     if(bcd3 != var_18h->bcd3){
  236.                                         var_10h->bcd3 = bcd3;
  237.                                         return var_18h;
  238.                                     }
  239.                                 }
  240.                             }else{
  241.                                 return var_18h;
  242.                             }
  243.                         }else{
  244.                             if((var_10h == 0) && (bcd2 <= var_18h->bcd2 + var_18h->size)){
  245.                                 var_10h = var_18h;
  246.                                 var_18h = var_18h->pNext;
  247.                             }
  248.  
  249.                             if(size + bcd2 < var_18h->bcd2){
  250.                                 break;
  251.                             }
  252.                         }
  253.                     }
  254.  
  255.                     var_10h->pNext = sectionHeaderCtor();
  256.                     pStructThree->arrUint32[0] = pStructThree->arrUint32[0] + 1;
  257.                     copySectionHeader(var_10h->pNext, pSectionHeaderName, size, bcd2, bcd3);
  258.                     var_10h->pNext->pNext = var_18h;
  259.                     return var_10h->pNext;
  260.                 }
  261.             }
  262.         }
  263.     }
  264. }
  265.  
  266. void fcn_64bc(uint32_t arg1, SectionHeader *pSectionHeader, uint32_t arg3){
  267.     // arg1 = [rbp - 0x4]
  268.     // arg2 = [rbp - 0x10]
  269.     // arg3 = [rbp - 0x8]
  270.  
  271.     // write to stderr
  272.     // this means that this function will be called when
  273.     // the program encounters an error
  274.     fwrite("[\x1b[31m-\x1b[0m] Segmentation Fault : ", 1, 0x22, stderr);
  275.  
  276.     if(pSectionHeader != NULL){
  277.         // esi = pSectionHeader->bcd2
  278.         // ecx = pSectionHeader->bcd3
  279.         // rdx = pSectionHeader->pName
  280.         // r8d = esi (lower 32-bit part of r8)
  281.  
  282.         fprintf(stderr, "%s-%d-0x%x : ", (const char*)pSectionHeader->pNext, pSectionHeader->bcd3, pSectionHeader->bcd2);
  283.     }
  284.  
  285.     if(arg1 != 3){
  286.         // here it must not be "<=" because we already checked
  287.         // that it is not equal to 3
  288.         if(arg1 < 3){
  289.             if(arg1 != 2){
  290.                 // same here, we already checked it is not 2
  291.                 if(arg1 < 2){
  292.                     if(arg1 != 0){
  293.                         if(arg1 != 1){
  294.                             // 65e0
  295.                             fwrite("XVM BRUH MOMENT\n", 1, 0x10, stderr);
  296.                         }else{ // arg1 == 1
  297.                             // 65a0
  298.                             // so arg3 is an address in our xvm bytecode!
  299.                             // one also, not that useful information is revealed here
  300.                             // it's that our bytecode is a 32 bit program
  301.                             // not useful because you might've already guessed
  302.                             // it's bytecode!
  303.                             fprintf(stderr, "Invalid Write @ 0x%x\n", arg3);
  304.                         }
  305.                     }else{ // arg1 == 0
  306.                         // 6580
  307.                         fprintf(stderr, "Invalid Read @ 0x%x\n", arg3);
  308.                     }
  309.                 }else{ // arg1 > 2
  310.                     // 65e0
  311.                     fwrite("XVM BRUH MOMENT\n", 1, 0x10, stderr);
  312.                 }
  313.             }else{ // arg1 == 2
  314.                 // 65c0
  315.                 fprintf(stderr, "Invalid Code @ 0x%x\n", arg3);
  316.             }
  317.         }else{ // arg1 > 3
  318.             // 65e0
  319.             fwrite("XVM BRUH MOMENT\n", 1, 0x10, stderr);
  320.         }
  321.     }else{ // arg1 == 3
  322.         // 655d
  323.         // looks like this function might be called from many functions
  324.         // so just in case let's store the function where it is called
  325.         // with the arguments and which block will get executed
  326.         //
  327.         // 1 > CALLED FROM : fcn_4c61
  328.         //         fcn_64bc(3, pSectionHeader, pSectionHeader->currentReadAddress + pSectionHeader->bcd2);
  329.         //
  330.         fprintf(stderr, "Invalid Address @ 0x%x\n", arg3);
  331.     }
  332.  
  333.     // arg1 == 3    [means invalid address]
  334.     // arg1 > 3     prints "bruh moment"
  335.     // arg1 < 3     checks further
  336.     // arg1 == 2    [means invalid code]
  337.     // arg1 > 2     prints "bruh moment"
  338.     // arg1 < 2     checks further
  339.     // arg1 == 0    [means invalid read]
  340.     // arg1 == 1    [means invalid write]
  341.     // arg1 != 1    prints bruh moment
  342.  
  343.     // exit
  344.     // this means that arg1 is our error code
  345.     exit(arg1);
  346.    
  347.     // below is the exit sequence I guess
  348.     // .
  349.     // .
  350.     // .
  351. }
  352.  
  353. // renamed from fcn_4c61
  354. uint32_t updateByteCode(SectionHeader* pSectionHeader, uint8_t arg2){
  355.     if(pSectionHeader->currentReadAddress >= pSectionHeader->size){
  356.         fcn_64bc(3, pSectionHeader, pSectionHeader->currentReadAddress + pSectionHeader->bcd2);
  357.     }
  358.  
  359.     pSectionHeader->pByteCode[pSectionHeader->currentReadAddress] = arg2;
  360.     pSectionHeader->currentReadAddress = pSectionHeader->currentReadAddress + 1;
  361.     return 1;
  362. }
  363.  
  364. // renamed fcn_422f to readByteCodeData;
  365. int32_t readByteCodeData(XVMHeader* pXVMHeader, const char* filename){
  366.     if(pXVMHeader == NULL){
  367.         return -1;        
  368.     }
  369.  
  370.     // fcn_46f4
  371.     if(checkIfFileIsOpen(pXVMHeader, filename) == -1){
  372.         fprintf(stderr, "[\x1b[31m-\x1b[0m] Cannot open \"%s\"\n", filename);
  373.         exit(-1);
  374.     }
  375.  
  376.     // fcn_3fff
  377.     checkValidXVMByteCode(pXVMHeader);
  378.  
  379.     // maybe magicValue[2] contains the total number of elements in this char** array
  380.     // this var_18h maybe pointer to the bytecode data!
  381.     uint32_t* var_18h = (uint32_t*)malloc(pXVMHeader->magicValue[2] << 3);
  382.     uint32_t i = 0;
  383.  
  384.     while(i < pXVMHeader->magicValue[2]){
  385.         fread((void*)(var_18h + i*8), 4, 1, pXVMHeader->pFile);
  386.         i++;
  387.     }
  388.  
  389.     // var_10h is pointer to a uint64_t array as seen by it's use below
  390.     SectionHeader* var_10h = NULL;
  391.     char* pSectionHeaderName = NULL;
  392.     size_t length = 0;
  393.    
  394.     uint32_t sectionHeaderData1 = 0;
  395.     uint32_t sectionHeaderData2 = 0;
  396.     uint32_t sectionHeaderData3 = 0;
  397.     uint32_t sectionHeaderData4 = 0;
  398.     uint32_t var_40h = 0;
  399.     uint32_t j = 0;
  400.  
  401.     while(j < pXVMHeader->magicValue[2]){
  402.         fread((void*)(&var_40h), 4, 1, pXVMHeader->pFile);
  403.        
  404.         // if you look at the hexdump of "pyaz.xvm", you will find "beef dead" in it
  405.         // in the beginning
  406.         if(var_40h != 0xdeadbeef){
  407.             // so this is checking for the validity of section header
  408.             // that means this function will read section header
  409.             // awesome
  410.             fwrite("[\x1b[31m-\x1b[0m] Corrupted Section Headers\n", 1, 0x27, stderr);
  411.             exit(1);
  412.         }
  413.  
  414.         // reads section header name
  415.         if(getdelim(&pSectionHeaderName, &length, 0, pXVMHeader->pFile) < 0){
  416.             fwrite("[\x1b[31m-\x1b[0m] Corrupted Section Headers\n", 1, 0x27, stderr);
  417.             exit(1);
  418.         }
  419.  
  420.         fread((void*)(&sectionHeaderData1), 4, 1, pXVMHeader->pFile);
  421.         fread((void*)(&sectionHeaderData2), 4, 1, pXVMHeader->pFile);
  422.         fread((void*)(&sectionHeaderData3), 4, 1, pXVMHeader->pFile);
  423.         fread((void*)(&sectionHeaderData4), 4, 1, pXVMHeader->pFile);
  424.  
  425.         if(sectionHeaderData1 > 0x10000){
  426.             sectionHeaderData1 = 0x10000;
  427.         }
  428.  
  429.         if(sectionHeaderData4 > 0x10000){
  430.             sectionHeaderData4 = 0x10000;
  431.         }
  432.  
  433.         // this means value of sectionHeaderData4 lies between
  434.         // sectionHeaderData1 and 0x10000
  435.         if(sectionHeaderData4 <= sectionHeaderData1){
  436.             sectionHeaderData4 = sectionHeaderData1;
  437.         }
  438.  
  439.         // guess this reads infromation about that section header by using it's name
  440.         var_10h = makeSectionHeader(pXVMHeader->pStructThree, pSectionHeaderName, sectionHeaderData1, sectionHeaderData2, sectionHeaderData3);
  441.         if(var_10h == NULL){
  442.             fprintf(stderr, "[\x1b[31m-\x1b[0m] Cannot Load Section (\"%s\") : FATAL @ 0x%x\n", pSectionHeaderName, sectionHeaderData2);
  443.             exit(-1);
  444.         }
  445.  
  446.         uint32_t var_34h = 0;
  447.         uint8_t c = 0;
  448.  
  449.         // 0xff is same as -1 when casted from uint8 to int8
  450.         while(c != 0xff){
  451.             // c is treated as character value here
  452.             fcn_4c61(var_10h, c);
  453.             var_34h++;
  454.  
  455.             if(var_34h < sectionHeaderData4){
  456.                 c = fgetc(pXVMHeader->pFile);
  457.             }
  458.         }
  459.  
  460.         j++;
  461.     }
  462.  
  463.     // free must be called after calling getdelim
  464.     free((void*)pSectionHeaderName);
  465.     pSectionHeaderName = NULL;
  466.  
  467.     // guess this is reading data section
  468.     // this might be our clue to find the password
  469.     var_10h = fcn_55db(pXVMHeader->pStructThree, ".data");
  470.     if(var_10h == NULL){
  471.         fwrite("[\x1b[31m-\x1b[0m] Corrupted section headers: \".data\" Not Found\n", 1, 0x3a, stderr);
  472.         exit(-1);
  473.     }
  474.  
  475.     uint32_t k = 0;
  476.     while(k < pXVMHeader->magicValue[2]){
  477.         // type of var_18h is ambiguous at this point because
  478.         // it's sometimes used as a pointer to uint64_t
  479.         // and sometimes uint32_t
  480.         // it will be clear once we start decoding other functions!
  481.         // so let it be as it is for now
  482.         if(var_18h[2*k] > var_10h[4]){
  483.             fprintf(stderr, "[\x1b[31m-\x1b[0m] Corrupted section headers: symbol offset (0x%x) is out of bounds for \".data\" section\n", var_18h[k]);
  484.             exit(-1);
  485.         }
  486.  
  487.         fcn_3b29(pXVMHeader->arr1, var_18h[k] + var_10h[1], var_18h[2*k+1]);
  488.  
  489.         k++;
  490.     }
  491.  
  492.     free((void*)var_18h);
  493.     var_18h = NULL;
  494.  
  495.     // stack check
  496.  
  497.     return 0;
  498. }
  499.  
  500. int main(int argc , char** argv){
  501.     int32_t var14_h = argc;
  502.     int64_t var20_h = (uint64_t)argv;
  503.    
  504.     if(var14_h != 2){
  505.         fwrite("xvm <bytecode>\n" , 1, 0x16 , stderr);
  506.         exit(-1);
  507.     }
  508.  
  509.     setbuf(stdin, NULL);
  510.     setbuf(stdout, NULL);
  511.  
  512.     // constructors
  513.     StructOne* pStructOne = structOneCtor();
  514.     XVMHeader* pXVMHeader = xvmHeaderCtor();
  515.  
  516.     readByteCodeData(pXVMHeader, argv[1]);
  517.  
  518.     makeSectionHeader(pXVMHeader->pStructThree, "stack", 0x3000, 0xcafe3000, 3);
  519.  
  520.     pStructOne->uint64arr[1] = pXVMHeader->magicValue[1];
  521.     pStructOne->uint64arr[3] = 0xcafe3ffc;
  522.     fcn_1997(pStructOne->uint64arr, pXVMHeader->magicValue);
  523.  
  524.  
  525.     // I suspect these may be destructors!
  526.     fcn_19de(pStructOne);
  527.     pStructOne = NULL;
  528.     fcn_47b3(pXVMHeader);
  529. }
  530.  
  531.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement