int32_t instr_group_5_ff_inc(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /0 * Increment r/m word by 1 * INC r/m16 */ uint16_t dst; MEM_WORD_READ(c, i->modrm.ea, &dst); INSTR_CALC_AND_SET_FLAGS(16, c, dst) MEM_WORD_WRITE(c, i->modrm.ea, dst); } else { /* FF /0 * Increment r/m doubleword by 1 * INC r/m32 */ uint32_t dst; MEM_DWORD_READ(c, i->modrm.ea, &dst); INSTR_CALC_AND_SET_FLAGS(32, c, dst) MEM_DWORD_WRITE(c, i->modrm.ea, dst); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /0 * Increment r/m word by 1 * INC r/m16 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm]) } else { /* FF /0 * Increment r/m doubleword by 1 * INC r/m32 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm]) } } return 0; }
int32_t instr_group_5_ff_push(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /6 * Push r/m16 * PUSH r/m16 */ uint16_t m16; MEM_WORD_READ(c,i->modrm.ea,&m16); PUSH_WORD(c, m16); } else { /* FF /6 * Push r/m32 * PUSH r/m32 */ uint32_t m32; MEM_DWORD_READ(c,i->modrm.ea,&m32); enum emu_segment oldseg = emu_memory_segment_get(c->mem); emu_memory_segment_select(c->mem, s_ss); PUSH_DWORD(c, m32); emu_memory_segment_select(c->mem, oldseg); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /6 * Push r/m16 * PUSH r/m16 */ PUSH_WORD(c, *c->reg16[i->modrm.rm]); } else { /* FF /6 * Push r/m32 * PUSH r/m32 */ PUSH_DWORD(c, c->reg[i->modrm.rm]); } } return 0; }
int32_t instr_mov_8b(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->prefixes & PREFIX_OPSIZE ) { /* 8B /r * Move r/m16 to r16 * MOV r16,r/m16 */ if( i->modrm.mod != 3 ) { MEM_WORD_READ(c, i->modrm.ea, c->reg16[i->modrm.opc]); //TRACK_INIT_REG16(c->instr, i->modrm.opc); } else { *c->reg16[i->modrm.opc] = *c->reg16[i->modrm.rm]; } } else { /* 8B /r * Move r/m32 to r32 * MOV r32,r/m32 */ if( i->modrm.mod != 3 ) { MEM_DWORD_READ(c, i->modrm.ea, &c->reg[i->modrm.opc]); //TRACK_INIT_REG32(c->instr, i->modrm.opc); } else { c->reg[i->modrm.opc] = c->reg[i->modrm.rm]; //TRACK_INIT_REG32(c->instr, i->modrm.opc); /*if ( c->tracking != NULL ) { c->tracking->track.reg[i->modrm.opc] = c->tracking->track.reg[i->modrm.rm]; }*/ } } return 0; }
//dzzie 5.19.11 - http://pdos.csail.mit.edu/6.828/2004/readings/i386/MOVS.htm int32_t instr_movs_a5(struct emu_cpu *c, struct emu_cpu_instruction *i) { if (i->prefixes & PREFIX_ADSIZE ) { UNIMPLEMENTED(c, SST); return 0; } uint8_t incSize = 0; if ( i->prefixes & PREFIX_OPSIZE ) //16bit { uint16_t tmp; MEM_WORD_READ(c, c->reg[esi], &tmp); MEM_WORD_WRITE(c, c->reg[edi], tmp); incSize = 2; } else{ //32bit uint32_t tmp2; MEM_DWORD_READ(c, c->reg[esi], &tmp2); MEM_DWORD_WRITE(c, c->reg[edi], tmp2); incSize = 4; } if (i->prefixes & PREFIX_F3) /* rep prefix - Copy ECX bytes from DS:[ESI] to ES:[EDI] */ { c->repeat_current_instr = false; if (c->reg[ecx] > 0 ){ c->reg[ecx]--; c->repeat_current_instr = true; }else{ return 0; //rep operation complete..do not adjust registers any more } } if ( !CPU_FLAG_ISSET(c,f_df) ){ /* increment */ c->reg[edi] += incSize; c->reg[esi] += incSize; } else{ /* decrement */ c->reg[edi] -= incSize; c->reg[esi] -= incSize; } return 0; }
int32_t instr_mov_a1(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->prefixes & PREFIX_OPSIZE ) { /* A1 * Move word at (seg:offset) to AX * MOV AX,moffs16* */ MEM_WORD_READ(c, i->disp, c->reg16[ax]); } else { /* A1 * Move doubleword at (seg:offset) to EAX * MOV EAX,moffs32* */ MEM_DWORD_READ(c, i->disp, &c->reg[eax]); //TRACK_INIT_REG32(c->instr, eax); } return 0; }
int32_t env_w32_hook_fclose(struct emu_env *env, struct emu_env_hook *hook) { logDebug(env->emu, "Hook me Captain Cook!\n"); logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__); struct emu_cpu *c = emu_cpu_get(env->emu); uint32_t eip_save; POP_DWORD(c, &eip_save); /* int _fcloseall( void ); int fclose( FILE *stream ); */ uint32_t p_stream; MEM_DWORD_READ(c, c->reg[esp], &p_stream); logDebug(env->emu, "fclose(0x%08x)\n", p_stream); emu_cpu_reg32_set(c, eax, 0); if (env->profile != NULL) { emu_profile_function_add(env->profile, "fclose"); emu_profile_argument_add_ptr(env->profile, "FILE *", "stream", p_stream); emu_profile_argument_add_none(env->profile); emu_profile_function_returnvalue_int_set(env->profile, "int", 0); } emu_cpu_eip_set(c, eip_save); return 0; }
int32_t instr_group_2_d3_shr(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /5 * Unsigned divide r/m16 by 2, CL times * SHR r/m16,CL */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *c->reg8[cl]); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D3 /5 * Unsigned divide r/m32 by 2, CL times * SHR r/m32,CL */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *c->reg8[cl]); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /5 * Unsigned divide r/m16 by 2, CL times * SHR r/m16,CL */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *c->reg8[cl]); } else { /* D3 /5 * Unsigned divide r/m32 by 2, CL times * SHR r/m32,CL */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *c->reg8[cl]); } } return 0; }
int32_t instr_group_2_c1_sar(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* C1 /7 ib * Signed divide* r/m16 by 2, imm8 times * SAR r/m16,imm8 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *i->imm8); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* C1 /7 ib * Signed divide* r/m32 by 2, imm8 times * SAR r/m32,imm8 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *i->imm8); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* C1 /7 ib * Signed divide* r/m16 by 2, imm8 times * SAR r/m16,imm8 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *i->imm8); } else { /* C1 /7 ib * Signed divide* r/m32 by 2, imm8 times * SAR r/m32,imm8 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *i->imm8); } } return 0; }
int32_t instr_group_2_d3_rcl(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /2 * Rotate 17 bits (CF,r/m16) left CL times * RCL r/m16,CL */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *c->reg8[cl]); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D3 /2 * Rotate 33 bits (CF,r/m32) left CL times * RCL r/m32,CL */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *c->reg8[cl]); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /2 * Rotate 17 bits (CF,r/m16) left CL times * RCL r/m16,CL */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *c->reg8[cl]); } else { /* D3 /2 * Rotate 33 bits (CF,r/m32) left CL times * RCL r/m32,CL */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *c->reg8[cl]); } } return 0; }
int32_t instr_group_3_f7_not(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /2 * Reverse each bit of r/m16 * NOT r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16) MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* F7 /2 * Reverse each bit of r/m32 * NOT r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32) MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /2 * Reverse each bit of r/m16 * NOT r/m16 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm]) } else { /* F7 /2 * Reverse each bit of r/m32 * NOT r/m32 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm]) } } return 0; }
int32_t instr_group_2_d1_sal(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /4 * Multiply r/m16 by 2, once * SAL r/m16,1 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, 1); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D1 /4 * Multiply r/m32 by 2, once * SAL r/m32,1 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, 1); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /4 * Multiply r/m16 by 2, once * SAL r/m16,1 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], 1); } else { /* D1 /4 * Multiply r/m32 by 2, once * SAL r/m32,1 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], 1); } } return 0; }
int32_t instr_group_5_ff_call(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->modrm.opc == 2 ) { PUSH_DWORD(c, c->eip); if( i->modrm.mod != 3 ) { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /2 * CALL r/m16 * Call near, absolute indirect, address given in r/m16 */ uint16_t disp; MEM_WORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } else { /* FF /2 * CALL r/m32 * Call near, absolute indirect, address given in r/m32 */ uint32_t disp; MEM_DWORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } } else { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /2 * CALL r/m16 * Call near, absolute indirect, address given in r/m16 */ c->eip = *c->reg16[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); TRACK_NEED_REG16(c->instr, i->modrm.rm); } else { /* FF /2 * CALL r/m32 * Call near, absolute indirect, address given in r/m32 */ c->eip = c->reg[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); TRACK_NEED_REG32(c->instr, i->modrm.rm); } } } else { /* FF /3 * CALL m16:16 * Call far, absolute indirect, address given in m16:16 */ /* FF /3 * CALL m16:32 * Call far, absolute indirect, address given in m16:32 */ UNIMPLEMENTED(c, SST); } return 0; }
int32_t instr_group_3_f7_imul(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /5 * DX:AX <- AX * r/m word * IMUL r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, *c->reg16[al], m16) DWORD_UPPER_TO_WORD(*c->reg16[dx],operation_result); DWORD_LOWER_TO_WORD(*c->reg16[ax],operation_result); INSTR_SET_FLAGS(c,*c->reg16[dx]); } else { /* F7 /5 * EDX:EAX <- EAX * r/m doubleword * IMUL r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, c->reg[eax], m32) QWORD_UPPER_TO_DWORD(c->reg[edx],operation_result); QWORD_LOWER_TO_DWORD(c->reg[eax],operation_result); INSTR_SET_FLAGS(c,c->reg[edx]); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /5 * DX:AX <- AX * r/m word * IMUL r/m16 */ INSTR_CALC(16, 32, c, *c->reg16[al], *c->reg16[i->modrm.rm]) DWORD_UPPER_TO_WORD(*c->reg16[dx],operation_result); DWORD_LOWER_TO_WORD(*c->reg16[ax],operation_result); INSTR_SET_FLAGS(c,*c->reg16[dx]); } else { /* F7 /5 * EDX:EAX <- EAX * r/m doubleword * IMUL r/m32 */ INSTR_CALC(32, 64, c, c->reg[eax], c->reg[i->modrm.rm]) QWORD_UPPER_TO_DWORD(c->reg[edx],operation_result); QWORD_LOWER_TO_DWORD(c->reg[eax],operation_result); INSTR_SET_FLAGS(c,c->reg[edx]); } } return 0; }
int32_t instr_imul_69(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 69 /r iw * word register <- r/m16 * immediate word * IMUL r16,imm16 * * word register <- r/m16 * immediate word * IMUL r16,r/m16,imm16 */ #if BYTE_ORDER == BIG_ENDIAN int16_t sexd; bcopy(i->imm16, &sexd, 2); #else int16_t sexd = (int16_t)*i->imm16; #endif uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, m16, sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 69 /r id * doubleword register <- r/m32 * immediate doubleword * IMUL r32,imm32 * * doubleword register <- r/m32 * immediate doubleword * IMUL r32,r/m32,imm32 */ int32_t sexd = (int32_t)i->imm; uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, m32, sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 69 /r iw * word register <- r/m16 * immediate word * IMUL r16,imm16 * * word register <- r/m16 * immediate word * IMUL r16,r/m16,imm16 */ #if BYTE_ORDER == BIG_ENDIAN int16_t sexd; bcopy(i->imm16, &sexd, 2); #else int16_t sexd = (int16_t)*i->imm16; #endif INSTR_CALC(16, 32, c, *c->reg16[i->modrm.rm], sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 69 /r id * doubleword register <- r/m32 * immediate doubleword * IMUL r32,imm32 * * doubleword register <- r/m32 * immediate doubleword * IMUL r32,r/m32,imm32 */ int32_t sexd = (int32_t)i->imm; INSTR_CALC(32, 64, c, c->reg[i->modrm.rm], sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t instr_imul_6b(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 6B /r ib * word register <- m16 * sign-extended immediate byte * IMUL r16,m16,imm8 */ int16_t sexd = (int8_t)*i->imm8; uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, m16, sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 6B /r ib * word register <- m16 * sign-extended immediate byte * IMUL r16,m16,imm8 */ int32_t sexd = (int8_t)*i->imm8; uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, m32, sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 6B /r ib * word register <- r16 * sign-extended immediate byte * IMUL r16,r16,imm8 * * word register <- word register * sign-extended immediate byte * IMUL r16,imm8 */ int16_t sexd = (int8_t)*i->imm8; INSTR_CALC(16, 32, c, *c->reg16[i->modrm.rm], sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 6B /r ib * doubleword register <- r32 * sign-extended immediate byte * IMUL r32,r32,imm8 * * doubleword register <- doubleword register * sign-extended immediate byte * IMUL r32,imm8 */ int32_t sexd = (int8_t)*i->imm8; INSTR_CALC(32, 64, c, c->reg[i->modrm.rm], sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t instr_imul_0f_af(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 0F AF /r * word register <- word register * r/m word * IMUL r16,r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, *c->reg16[i->modrm.opc], m16) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 0F AF /r * doubleword register <- doubleword register * r/m doubleword * IMUL r32,r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, c->reg[i->modrm.opc], m32) c->reg[i->modrm.opc] = operation_result; uint16_t high; DWORD_UPPER_TO_WORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 0F AF /r * word register <- word register * r/m word * IMUL r16,r/m16 */ INSTR_CALC(16, 32, c, *c->reg16[i->modrm.opc], *c->reg16[i->modrm.rm]) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 0F AF /r * doubleword register <- doubleword register * r/m doubleword * IMUL r32,r/m32 */ INSTR_CALC(32, 64, c, c->reg[i->modrm.opc], c->reg[i->modrm.rm]) c->reg[i->modrm.opc] = operation_result; uint16_t high; DWORD_UPPER_TO_WORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t env_w32_hook_fopen(struct emu_env *env, struct emu_env_hook *hook) { logDebug(env->emu, "Hook me Captain Cook!\n"); logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__); struct emu_cpu *c = emu_cpu_get(env->emu); uint32_t eip_save; POP_DWORD(c, &eip_save); /* FILE *fopen( const char *filename, const char *mode ); FILE *_wfopen( const wchar_t *filename, const wchar_t *mode ); */ uint32_t p_filename; MEM_DWORD_READ(c, c->reg[esp], &p_filename); struct emu_string *filename = emu_string_new(); emu_memory_read_string(c->mem, p_filename, filename, 512); uint32_t p_mode; MEM_DWORD_READ(c, c->reg[esp]+4, &p_mode); struct emu_string *mode = emu_string_new(); emu_memory_read_string(c->mem, p_mode, mode, 512); // printf("fopen(%s, %s)\n", emu_string_char(filename), (char *)mode->data); uint32_t returnvalue; if ( hook->hook.win->userhook != NULL ) { returnvalue = hook->hook.win->userhook(env, hook, emu_string_char(filename), emu_string_char(mode)); }else { returnvalue = 0x89898989; } emu_cpu_reg32_set(c, eax, returnvalue); if (env->profile != NULL) { emu_profile_function_add(env->profile, "fopen"); emu_profile_argument_add_ptr(env->profile, "const char *", "filename", p_filename); emu_profile_argument_add_string(env->profile, "", "", emu_string_char(filename)); emu_profile_argument_add_ptr(env->profile, "const char *", "mode", p_mode); emu_profile_argument_add_string(env->profile, "", "", emu_string_char(mode)); emu_profile_function_returnvalue_ptr_set(env->profile, "FILE *", returnvalue); emu_profile_argument_add_none(env->profile); } emu_string_free(filename); emu_string_free(mode); emu_cpu_eip_set(c, eip_save); return 0; }
int32_t instr_group_5_ff_jmp(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->modrm.opc == 4 ) { if( i->modrm.mod != 3 ) { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /4 * Jump near, absolute indirect, address given in r/m16 * JMP r/m16 */ uint16_t disp; MEM_WORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } else { /* FF /4 * Jump near, absolute indirect, address given in r/m32 * JMP r/m32 */ uint32_t disp; MEM_DWORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } } else { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /4 * Jump near, absolute indirect, address given in r/m16 * JMP r/m16 */ c->eip = *c->reg16[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); //TRACK_NEED_REG16(c->instr, i->modrm.rm); } else { /* FF /4 * Jump near, absolute indirect, address given in r/m32 * JMP r/m32 */ c->eip = c->reg[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); //TRACK_NEED_REG32(c->instr, i->modrm.rm); } } } else /* /5 */ { /* unneeded */ /* FF /5 * Jump far, absolute indirect, address given in m16:16 * JMP m16:16 */ /* FF /5 * Jump far, absolute indirect, address given in m16:32 * JMP m16:32 */ UNIMPLEMENTED(c, SST); } return 0; }
int32_t instr_group_2_d1_rcr(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /3 * Rotate 17 bits (CF,r/m16) right once * RCR r/m16,1 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, 1); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D1 /3 * Rotate 33 bits (CF,r/m32) right once * RCR r/m32,1 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, 1); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /3 * Rotate 17 bits (CF,r/m16) right once * RCR r/m16,1 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], 1); } else { /* D1 /3 * Rotate 33 bits (CF,r/m32) right once * RCR r/m32,1 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], 1); } } return 0; }
int32_t instr_lods_ad(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->prefixes & PREFIX_OPSIZE ) { /* AD * Load word at address DS:(E)SI into AX * LODS m16 */ /* AD * Load word at address DS:(E)SI into AX * LODSW */ if ( i->prefixes & PREFIX_ADSIZE ) { // MEM_WORD_READ(c, c->reg16[si], c->reg16[ax]); UNIMPLEMENTED(c, SST); } else { MEM_WORD_READ(c, c->reg[esi], c->reg16[ax]); if (CPU_FLAG_ISSET(c,f_df)) { /* decrement */ c->reg[esi] -= 2; }else { /* increment */ c->reg[esi] += 2; } } } else { /* AD * Load doubleword at address DS:(E)SI into EAX * LODS m32 */ /* AD * Load doubleword at address DS:(E)SI into EAX * LODSD */ if ( i->prefixes & PREFIX_ADSIZE ) { // MEM_DWORD_READ(c, c->reg16[si], &c->reg[eax]); UNIMPLEMENTED(c, SST); } else { MEM_DWORD_READ(c, c->reg[esi], &c->reg[eax]); if (CPU_FLAG_ISSET(c,f_df)) { /* decrement */ c->reg[esi] -= 4; }else { /* increment */ c->reg[esi] += 4; } //TRACK_INIT_REG32(c->instr, eax); } } return 0; }
int32_t env_w32_hook_fwrite(struct emu_env *env, struct emu_env_hook *hook) { logDebug(env->emu, "Hook me Captain Cook!\n"); logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__); struct emu_cpu *c = emu_cpu_get(env->emu); uint32_t eip_save; POP_DWORD(c, &eip_save); /* size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); */ uint32_t p_buffer; MEM_DWORD_READ(c, c->reg[esp], &p_buffer); uint32_t size; MEM_DWORD_READ(c, (c->reg[esp]+4), &size); uint32_t count; MEM_DWORD_READ(c, (c->reg[esp]+8), &count); unsigned char *buffer = malloc(size*count); emu_memory_read_block(emu_memory_get(env->emu), p_buffer, buffer, size*count); uint32_t p_stream; MEM_DWORD_READ(c, c->reg[esp]+12, &p_stream); uint32_t returnvalue; if ( hook->hook.win->userhook != NULL ) { returnvalue = hook->hook.win->userhook(env, hook, buffer, size, count, p_stream); }else { returnvalue = size*count; } logDebug(env->emu, "fwrite(0x%08x, %d, %d, 0x%08x)\n", p_buffer, size, count, p_stream); emu_cpu_reg32_set(c, eax, returnvalue); if ( env->profile != NULL ) { emu_profile_function_add(env->profile, "fwrite"); emu_profile_function_returnvalue_int_set(env->profile, "size_t", returnvalue); emu_profile_argument_add_ptr(env->profile, "const void *", "buffer", p_buffer); emu_profile_argument_add_bytea(env->profile, "", "", buffer, size*count); emu_profile_argument_add_int(env->profile, "size_t", "size", size); emu_profile_argument_add_int(env->profile, "count_t", "count", count); emu_profile_argument_add_ptr(env->profile, "FILE *", "stream", p_stream); emu_profile_argument_add_none(env->profile); } free(buffer); emu_cpu_eip_set(c, eip_save); return 0; }