2011-10-23 17:48:10 -07:00
|
|
|
#include "pyc_module.h"
|
2009-07-24 08:35:21 +00:00
|
|
|
#include "data.h"
|
2018-01-28 14:33:26 -08:00
|
|
|
#include <stdexcept>
|
2025-02-28 00:39:00 +08:00
|
|
|
#include <cstring>
|
2009-07-24 08:35:21 +00:00
|
|
|
|
|
|
|
void PycModule::setVersion(unsigned int magic)
|
|
|
|
{
|
|
|
|
// Default for versions that don't support unicode selection
|
|
|
|
m_unicode = false;
|
|
|
|
|
|
|
|
switch (magic) {
|
|
|
|
case MAGIC_1_0:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 0;
|
|
|
|
break;
|
|
|
|
case MAGIC_1_1:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 1;
|
|
|
|
break;
|
|
|
|
case MAGIC_1_3:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 3;
|
|
|
|
break;
|
|
|
|
case MAGIC_1_4:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 4;
|
|
|
|
break;
|
|
|
|
case MAGIC_1_5:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Starting with 1.6, Python adds +1 for unicode mode (-U) */
|
|
|
|
case MAGIC_1_6+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_1_6:
|
|
|
|
m_maj = 1;
|
|
|
|
m_min = 6;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_0+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_0:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 0;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_1+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_1:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 1;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_2+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_2:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 2;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_3+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_3:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 3;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_4+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_4:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 4;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_5+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_5:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 5;
|
|
|
|
break;
|
|
|
|
case MAGIC_2_6+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_6:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 6;
|
|
|
|
break;
|
2010-08-31 23:17:38 -07:00
|
|
|
case MAGIC_2_7+1:
|
|
|
|
m_unicode = true;
|
|
|
|
/* Fall through */
|
|
|
|
case MAGIC_2_7:
|
|
|
|
m_maj = 2;
|
|
|
|
m_min = 7;
|
2010-09-02 01:01:05 -07:00
|
|
|
break;
|
2009-07-24 08:35:21 +00:00
|
|
|
|
|
|
|
/* 3.0 and above are always unicode */
|
|
|
|
case MAGIC_3_0+1:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 0;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
case MAGIC_3_1+1:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 1;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2011-01-06 17:15:48 -08:00
|
|
|
/* 3.2 stops using the unicode increment */
|
|
|
|
case MAGIC_3_2:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 2;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2012-05-26 13:50:23 -07:00
|
|
|
case MAGIC_3_3:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 3;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2013-11-27 14:10:05 -08:00
|
|
|
case MAGIC_3_4:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 4;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2015-10-01 16:06:09 -07:00
|
|
|
case MAGIC_3_5:
|
2018-01-28 14:33:26 -08:00
|
|
|
/* fall through */
|
2017-04-09 18:06:52 +05:30
|
|
|
|
|
|
|
case MAGIC_3_5_3:
|
2015-10-01 16:06:09 -07:00
|
|
|
m_maj = 3;
|
|
|
|
m_min = 5;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2016-06-22 22:06:09 -07:00
|
|
|
case MAGIC_3_6:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 6;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2017-12-20 13:15:03 -08:00
|
|
|
case MAGIC_3_7:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 7;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2019-02-08 16:06:55 -08:00
|
|
|
case MAGIC_3_8:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 8;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2020-09-29 09:28:15 -07:00
|
|
|
case MAGIC_3_9:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 9;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
2021-04-12 11:03:36 -07:00
|
|
|
|
2021-10-10 00:52:41 +05:30
|
|
|
case MAGIC_3_10:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 10;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
2021-04-12 11:03:36 -07:00
|
|
|
|
2022-12-02 16:34:58 -08:00
|
|
|
case MAGIC_3_11:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 11;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2023-11-09 11:11:37 -08:00
|
|
|
case MAGIC_3_12:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 12;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2024-08-08 01:39:40 +03:00
|
|
|
case MAGIC_3_13:
|
|
|
|
m_maj = 3;
|
|
|
|
m_min = 13;
|
|
|
|
m_unicode = true;
|
|
|
|
break;
|
|
|
|
|
2009-07-24 08:35:21 +00:00
|
|
|
/* Bad Magic detected */
|
|
|
|
default:
|
|
|
|
m_maj = -1;
|
|
|
|
m_min = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 14:51:23 -07:00
|
|
|
bool PycModule::isSupportedVersion(int major, int minor)
|
|
|
|
{
|
|
|
|
switch (major) {
|
|
|
|
case 1:
|
|
|
|
return (minor >= 0 && minor <= 6);
|
|
|
|
case 2:
|
|
|
|
return (minor >= 0 && minor <= 7);
|
|
|
|
case 3:
|
2023-11-09 11:11:37 -08:00
|
|
|
return (minor >= 0 && minor <= 12);
|
2022-10-04 14:51:23 -07:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-24 08:35:21 +00:00
|
|
|
void PycModule::loadFromFile(const char* filename)
|
|
|
|
{
|
|
|
|
PycFile in(filename);
|
|
|
|
if (!in.isOpen()) {
|
|
|
|
fprintf(stderr, "Error opening file %s\n", filename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setVersion(in.get32());
|
|
|
|
if (!isValid()) {
|
2018-01-28 10:32:44 -08:00
|
|
|
fputs("Bad MAGIC!\n", stderr);
|
2009-07-24 08:35:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-26 14:31:21 -07:00
|
|
|
int flags = 0;
|
|
|
|
if (verCompare(3, 7) >= 0)
|
|
|
|
flags = in.get32();
|
|
|
|
|
|
|
|
if (flags & 0x1) {
|
|
|
|
// Optional checksum added in Python 3.7
|
|
|
|
in.get32();
|
|
|
|
in.get32();
|
|
|
|
} else {
|
|
|
|
in.get32(); // Timestamp -- who cares?
|
|
|
|
|
|
|
|
if (verCompare(3, 3) >= 0)
|
|
|
|
in.get32(); // Size parameter added in Python 3.3
|
|
|
|
}
|
2012-05-26 13:50:23 -07:00
|
|
|
|
2022-12-01 16:13:31 -08:00
|
|
|
m_code = LoadObject(&in, this).cast<PycCode>();
|
2009-07-24 08:35:21 +00:00
|
|
|
}
|
|
|
|
|
2022-06-16 12:49:04 +01:00
|
|
|
void PycModule::loadFromMarshalledFile(const char* filename, int major, int minor)
|
|
|
|
{
|
2022-06-15 11:33:11 +01:00
|
|
|
PycFile in (filename);
|
|
|
|
if (!in.isOpen()) {
|
|
|
|
fprintf(stderr, "Error opening file %s\n", filename);
|
|
|
|
return;
|
|
|
|
}
|
2022-10-04 14:51:23 -07:00
|
|
|
if (!isSupportedVersion(major, minor)) {
|
|
|
|
fprintf(stderr, "Unsupported version %d.%d\n", major, minor);
|
2022-06-15 11:33:11 +01:00
|
|
|
return;
|
|
|
|
}
|
2022-10-04 14:51:23 -07:00
|
|
|
m_maj = major;
|
|
|
|
m_min = minor;
|
|
|
|
m_unicode = (major >= 3);
|
2022-12-01 16:13:31 -08:00
|
|
|
m_code = LoadObject(&in, this).cast<PycCode>();
|
2022-06-15 11:33:11 +01:00
|
|
|
}
|
|
|
|
|
2025-02-27 16:10:30 +08:00
|
|
|
void PycModule::loadFromOneshotSequenceFile(const char *filename)
|
|
|
|
{
|
|
|
|
PycFile in(filename);
|
|
|
|
if (!in.isOpen())
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error opening file %s\n", filename);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool oneshot_seq_header = true;
|
|
|
|
while (oneshot_seq_header)
|
|
|
|
{
|
|
|
|
int indicator = in.getByte();
|
|
|
|
switch (indicator)
|
|
|
|
{
|
|
|
|
case 0xA1:
|
|
|
|
in.getBuffer(16, this->pyarmor_aes_key);
|
|
|
|
break;
|
|
|
|
case 0xA2:
|
|
|
|
in.getBuffer(12, this->pyarmor_mix_str_aes_nonce);
|
|
|
|
break;
|
|
|
|
case 0xF0:
|
|
|
|
break;
|
|
|
|
case 0xFF:
|
|
|
|
oneshot_seq_header = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "Unknown 1-shot sequence indicator %02X\n", indicator);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write only. Some fields unknown to us or not needed for decryption are discarded.
|
|
|
|
char discard_buffer[64];
|
|
|
|
|
|
|
|
char pyarmor_header[64];
|
|
|
|
in.getBuffer(64, pyarmor_header);
|
|
|
|
this->m_maj = pyarmor_header[9];
|
|
|
|
this->m_min = pyarmor_header[10];
|
|
|
|
this->m_unicode = (m_maj >= 3);
|
|
|
|
|
|
|
|
unsigned int remain_header_length = *(unsigned int *)(pyarmor_header + 28) - 64;
|
|
|
|
while (remain_header_length)
|
|
|
|
{
|
|
|
|
unsigned int discard_length = (remain_header_length > 64) ? 64 : remain_header_length;
|
|
|
|
in.getBuffer(discard_length, discard_buffer);
|
|
|
|
remain_header_length -= discard_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For 1-shot sequence, the following part has been decrypted once.
|
|
|
|
unsigned int code_object_offset = in.get32();
|
2025-02-28 00:39:00 +08:00
|
|
|
unsigned int xor_key_procedure_length = in.get32();
|
|
|
|
this->pyarmor_co_code_aes_nonce_xor_enabled = (xor_key_procedure_length > 0);
|
2025-02-27 16:10:30 +08:00
|
|
|
unsigned int remain_second_part_length = code_object_offset - 8;
|
|
|
|
while (remain_second_part_length)
|
|
|
|
{
|
|
|
|
unsigned int discard_length = (remain_second_part_length > 64) ? 64 : remain_second_part_length;
|
|
|
|
in.getBuffer(discard_length, discard_buffer);
|
|
|
|
remain_second_part_length -= discard_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->pyarmor_co_code_aes_nonce_xor_enabled)
|
|
|
|
{
|
2025-02-28 00:39:00 +08:00
|
|
|
char *procedure_buffer = (char *)malloc(xor_key_procedure_length);
|
|
|
|
in.getBuffer(xor_key_procedure_length, procedure_buffer);
|
|
|
|
pyarmorCoCodeAesNonceXorKeyCalculate(
|
|
|
|
procedure_buffer,
|
|
|
|
xor_key_procedure_length,
|
|
|
|
this->pyarmor_co_code_aes_nonce_xor_key);
|
2025-03-01 17:27:06 +08:00
|
|
|
free(procedure_buffer);
|
2025-02-27 16:10:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
m_code = LoadObject(&in, this).cast<PycCode>();
|
|
|
|
}
|
|
|
|
|
2025-02-28 14:38:42 +08:00
|
|
|
#define GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(CUR, REF) \
|
|
|
|
do \
|
|
|
|
{ \
|
2025-02-28 00:39:00 +08:00
|
|
|
unsigned char _INSIDE_LOW_NIBBLE = (CUR)[1] & 0xF; \
|
2025-02-28 14:38:42 +08:00
|
|
|
if (valid_index[_INSIDE_LOW_NIBBLE] != -1) \
|
|
|
|
{ \
|
|
|
|
(REF) = registers[_INSIDE_LOW_NIBBLE]; \
|
|
|
|
(CUR) += 2; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
unsigned int _INSIDE_SIZE = (CUR)[1] & 0x7; \
|
|
|
|
if (_INSIDE_SIZE == 1) \
|
|
|
|
{ \
|
|
|
|
(REF) = *(char *)((CUR) + 2); \
|
|
|
|
(CUR) += 3; \
|
|
|
|
} \
|
|
|
|
else if (_INSIDE_SIZE == 2) \
|
|
|
|
{ \
|
|
|
|
(REF) = *(short *)((CUR) + 2); \
|
|
|
|
(CUR) += 4; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
(REF) = *(int *)((CUR) + 2); \
|
|
|
|
(CUR) += 6; \
|
|
|
|
} \
|
|
|
|
} \
|
2025-02-28 00:39:00 +08:00
|
|
|
} while (0)
|
|
|
|
|
2025-03-01 15:25:03 +08:00
|
|
|
void pyarmorCoCodeAesNonceXorKeyCalculate(const char *in_buffer, unsigned int in_buffer_length, unsigned char *out_buffer)
|
2025-02-28 00:39:00 +08:00
|
|
|
{
|
|
|
|
unsigned char *cur = (unsigned char *)in_buffer + 16;
|
|
|
|
unsigned char *end = (unsigned char *)in_buffer + in_buffer_length;
|
2025-02-28 14:38:42 +08:00
|
|
|
int registers[8] = {0};
|
2025-02-28 00:39:00 +08:00
|
|
|
const int valid_index[16] = {
|
2025-02-28 14:38:42 +08:00
|
|
|
0,
|
|
|
|
1,
|
|
|
|
2,
|
|
|
|
3,
|
|
|
|
4,
|
|
|
|
5,
|
|
|
|
-1,
|
|
|
|
7, /* origin is 15 */
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
|
|
|
-1,
|
2025-02-28 00:39:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
while (cur < end)
|
|
|
|
{
|
2025-02-28 14:38:42 +08:00
|
|
|
int operand_2 = 0;
|
2025-03-01 17:27:06 +08:00
|
|
|
unsigned char high_nibble = 0;
|
|
|
|
unsigned char reg = 0;
|
2025-02-28 00:39:00 +08:00
|
|
|
switch (*cur)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
// terminator
|
|
|
|
cur++;
|
|
|
|
break;
|
|
|
|
case 2:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
|
|
|
registers[high_nibble] += operand_2;
|
|
|
|
break;
|
|
|
|
case 3:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
|
|
|
registers[high_nibble] -= operand_2;
|
|
|
|
break;
|
|
|
|
case 4:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
2025-02-28 14:38:42 +08:00
|
|
|
registers[high_nibble] *= operand_2;
|
|
|
|
/** We found that in x86_64, machine code is
|
|
|
|
* imul reg64, reg/imm
|
|
|
|
* so we get the low bits of the result.
|
|
|
|
*/
|
2025-02-28 00:39:00 +08:00
|
|
|
break;
|
|
|
|
case 5:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
2025-02-28 14:38:42 +08:00
|
|
|
registers[high_nibble] /= operand_2;
|
|
|
|
/** We found that in x86_64, machine code is
|
|
|
|
* mov r10d, imm32 ; when necessary
|
|
|
|
* mov rax, reg64
|
|
|
|
* cqo
|
|
|
|
* idiv r10/reg64 ; r10/reg64 is the operand_2
|
|
|
|
* mov reg64, rax
|
|
|
|
* so rax (0) is tampered.
|
|
|
|
*/
|
|
|
|
registers[0] = registers[high_nibble];
|
2025-02-28 00:39:00 +08:00
|
|
|
break;
|
|
|
|
case 6:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
|
|
|
registers[high_nibble] ^= operand_2;
|
|
|
|
break;
|
|
|
|
case 7:
|
2025-03-01 17:27:06 +08:00
|
|
|
high_nibble = cur[1] >> 4;
|
2025-02-28 00:39:00 +08:00
|
|
|
GET_REAL_OPERAND_2_AND_ADD_CURRENT_PTR(cur, operand_2);
|
|
|
|
registers[high_nibble] = operand_2;
|
|
|
|
break;
|
|
|
|
case 8:
|
2025-02-28 14:38:42 +08:00
|
|
|
/** We found that in x86_64, machine code is
|
|
|
|
* mov reg1, ptr [reg2]
|
|
|
|
* This hardly happens.
|
|
|
|
*/
|
2025-02-28 00:39:00 +08:00
|
|
|
cur += 2;
|
|
|
|
break;
|
|
|
|
case 9:
|
2025-03-01 17:27:06 +08:00
|
|
|
reg = cur[1] & 0x7;
|
2025-02-28 14:38:42 +08:00
|
|
|
*(int *)out_buffer = registers[reg];
|
2025-02-28 00:39:00 +08:00
|
|
|
cur += 2;
|
|
|
|
break;
|
|
|
|
case 0xA:
|
|
|
|
/**
|
|
|
|
* This happens when 4 bytes of total 12 bytes nonce are calculated,
|
|
|
|
* and the result is to be stored in the memory. So the address from
|
|
|
|
* register 7 (15) is moved to one of the registers.
|
|
|
|
*
|
|
|
|
* We don't really care about the address and the register number.
|
|
|
|
* So we just skip 6 bytes (0A ... and 02 ...).
|
|
|
|
*
|
|
|
|
* For example:
|
|
|
|
*
|
|
|
|
* [0A [1F] 00] - [00][011][111] - mov rbx<3>, [rbp<7>-18h]
|
|
|
|
* [rbp-18h] is the address
|
|
|
|
* [02 [39] 0C] - [0011][1][001] - add rbx<3>, 0Ch
|
|
|
|
* 0Ch is a fixed offset
|
|
|
|
* [09 [98] ] - [10][011][000] - mov [rbx<3>], eax<0>
|
|
|
|
* eax<0> is the value to be stored
|
2025-02-28 14:38:42 +08:00
|
|
|
*
|
2025-02-28 00:39:00 +08:00
|
|
|
* Another example:
|
2025-02-28 14:38:42 +08:00
|
|
|
*
|
2025-02-28 00:39:00 +08:00
|
|
|
* [0A [07] 00] - [00][000][111] - mov rax<0>, [rbp<7>-18h]
|
|
|
|
* [02 [09] 0C] - [0000][1][001] - add rax<0>, 0Ch
|
|
|
|
* [0B [83] 04] - [10][000][011] - mov [rax<0>+4], ebx<3>
|
|
|
|
* 4 means [4..8] of 12 bytes nonce
|
|
|
|
*/
|
|
|
|
cur += 6;
|
|
|
|
break;
|
|
|
|
case 0xB:
|
2025-03-01 17:27:06 +08:00
|
|
|
reg = cur[1] & 0x7;
|
|
|
|
*(int *)(out_buffer + cur[2]) = registers[reg];
|
2025-02-28 00:39:00 +08:00
|
|
|
cur += 3;
|
|
|
|
break;
|
|
|
|
default:
|
2025-03-01 17:27:06 +08:00
|
|
|
fprintf(stderr, "FATAL: Unknown opcode %d at %lld\n", *cur, cur - (unsigned char *)in_buffer);
|
2025-02-28 00:39:00 +08:00
|
|
|
memset(out_buffer, 0, 12);
|
|
|
|
cur = end;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 00:07:34 -08:00
|
|
|
PycRef<PycString> PycModule::getIntern(int ref) const
|
2009-07-24 08:35:21 +00:00
|
|
|
{
|
2022-12-01 11:35:14 -08:00
|
|
|
if (ref < 0 || (size_t)ref >= m_interns.size())
|
2018-01-28 14:33:26 -08:00
|
|
|
throw std::out_of_range("Intern index out of range");
|
2022-12-01 11:35:14 -08:00
|
|
|
return m_interns[(size_t)ref];
|
2014-01-21 00:07:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
PycRef<PycObject> PycModule::getRef(int ref) const
|
|
|
|
{
|
2022-12-01 11:35:14 -08:00
|
|
|
if (ref < 0 || (size_t)ref >= m_refs.size())
|
2018-01-28 14:33:26 -08:00
|
|
|
throw std::out_of_range("Ref index out of range");
|
2022-12-01 11:35:14 -08:00
|
|
|
return m_refs[(size_t)ref];
|
2009-07-24 08:35:21 +00:00
|
|
|
}
|