In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-09 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article shows you the selection and transformation of the disassembly engine in the ollydbg debugger. The content is concise and easy to understand, which will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
Although the editor chooses udis86,od 's disassembly engine ODDisassm, although concise, it only supports x86intel assembly instructions, not x64, and the instruction set is also very obsolete. Although BeaEngine also supports many new instruction sets, the code style looks uncomfortable. Although capstone supports many instruction sets and mobile arm instructions, the overall code is complex, huge and bloated, and the transformation cost is too high. Finally, it chose udis86. Code and interface are very simple only a few cpp/h files, support MMX, FPU (x87), AMD 3DNow, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES, AMD-V, INTEL-VMX, SMX, support x86/x64 Intel/AT&An instruction platform, and one of the biggest features is that the decoding speed is very fast.
1. The use of udis86
The interface of udis86 is very simple and easy to use.
First, the first step is to initialize
Ud_t ud_obj
Ud_init & ud_obj)
Ud_set_mode (& ud_obj,16); sets the disassembly system 16-32-64 bit
Ud_set_pc (u, 0); sets the base address of the segment in memory, which is equivalent to the base address of the PE file.
Ud_set_asm_buffer (uther u-> asm_buf_int,sizeof (u-> asm_buf_int)); sets the original address and length of the disassembled data
Ud_set_syntax (& ud_obj, UD_SYN_INTEL); sets the syntax platform for disassembly
The second step is to disassemble the call
Code example:
While (ud_disassemble & ud_obj) {
If (o_do_off)
Printf ("6" FMT64 "x", ud_insn_off (& ud_obj))
If (o_do_hex) {
Const char* hex1, * hex2
Hex1 = ud_insn_hex (& ud_obj)
Hex2 = hex1 + 16
Printf ("%-16.16s%-24s", hex1, ud_insn_asm (& ud_obj))
If (strlen (hex1) > 16) {
/ / printf ("\ n")
If (o_do_off)
Printf ("s -", "")
Printf ("%-16s", hex2)
}
}
Else printf (%-24s), ud_insn_asm (& ud_obj)
Printf ("\ n")
}
Ud_disassemble (& ud_obj) disassembly parsing instruction
The ud_decode function is called in ud_disassemble to implement the decoding and analysis operation, and then the translator function is used to translate the decoded result into a readable intel or AT&T syntax string.
Ud_insn_off (& ud_obj) gets the current instruction address
Ud_insn_asm (& ud_obj) gets the current disassembled string.
The following is the result:
Third, the setting of symbols
Udis86 also provides a function interface for setting parsing symbols.
Ud_set_sym_resolver & ud_obj,resolver)
Interface definition of resolver:
Const char* (* resolver) (struct ud*
Uint64_t addr
Int64_t * offset)
We can see that in the code
Void
Ud_syn_print_addr (struct ud * u, uint64_t addr,char operand_asm_buf [64], int*index)
{
Const char * name = NULL
If (u-> sym_resolver) {
Int64_t offset = 0
Name = u-> sym_resolver (u, addr, & offset)
If (name) {
If (offset) {
Ud_asmprintf (u, "% s% +" FMT64 "d", name,offset)
Ud_asmprintf2 (operand_asm_buf,index, "% s% +" FMT64 "d", name, offset)
} else {
Ud_asmprintf (u, "% s", name)
Ud_asmprintf2 (operand_asm_buf,index, "% s", name)
}
Return
}
}
Ud_asmprintf (u, "%" FMT64 "X", addr)
Ud_asmprintf2 (operand_asm_buf,index, "%" FMT64 "X", addr)
}
If the sym_resolver interface is set, it will be called to disassemble the symbol string instead of the disassembly string of the address value.
Throughout the above udis86 provides a lot of functions, but in some cases there are many shortcomings, such as in a large piece of memory for disassembly and decoding without pre-decoding function interface, will cause users to mistakenly think that the efficiency is not high, there are other situations with us to use ollydbg grammar style also need to be modified.
2. Udis86 transformation
First, add pre-analysis interface.
Unsigned int ud_predecode (struct ud* u)
{
Int len
If (u-> inp_end) {
Return 0
}
Len = ud_decode (u)
Return len
}
This function is very fast and efficient in analyzing the parsing process, and this function is mainly used in pre-analysis to determine how many lines of instructions can be disassembled from the current memory data, so as to facilitate subsequent interface display when paging display. Because it lacks the translator process, the efficiency of the pre-analysis process is improved hundreds of times.
Two. modification of address prefix display
The prefix result of the address of udis86 is different from that of ollydbg, for example
Static voidopr_cast (struct ud* u, struct ud_operand* op) {if (u-> br_far) {ud_asmprintf (u, "far");} switch (op- > size) {case 8: ud_asmprintf (u, "byte"); break; case 16: ud_asmprintf (u, "word"); break; case 32: ud_asmprintf (u, "dword"); break; case 64: ud_asmprintf (u, "qword"); break Case 80: ud_asmprintf (u, "tword"); break; default: break;}} in order to keep ollydbg, we need to change it to: switch (op- > size) {case 8: ud_asmprintf (u, "BYTE PTR"); ud_asmprintf2 (operand_asm_buf,index, "BYTE PTR"); break; case 16: ud_asmprintf (u, "WORD PTR"); ud_asmprintf2 (operand_asm_buf,index, "WORD PTR"); break Case 32: ud_asmprintf (u, "DWORD PTR"); ud_asmprintf2 (operand_asm_buf,index, "DWORD PTR"); break; case 64: ud_asmprintf (u, "QWORD PTR"); ud_asmprintf2 (operand_asm_buf,index, "QWORD PTR"); break; case 80: ud_asmprintf (u, "TWORD PTR"); ud_asmprintf2 (operand_asm_buf,index, "TWORD PTR"); break; default: break;}
X64 RIP call instruction cannot display symbolic address
This should be a bug display problem, so we need to make the following changes, the problem is mainly in ud_syn_print_mem_disp
Function, the original function code is:
Voidud_syn_print_mem_disp (struct ud* u, const struct ud_operand * op, int sign,char operand_asm_buf [64], int*index) {UD_ASSERT (op- > offset = 0); if (op- > base = = UD_NONE&& op- > index== UD_NONE) {uint64_t v; UD_ASSERT (op- > scale = = UD_NONE&& op- > offset = 8) / * unsigned mem-offset * / switch (op- > offset) {case 16: v = op- > lval.uword; break; case 32: v = op- > lval.udword; break; case 64: v = op- > lval.uqword; break; default: UD_ASSERT (! "invalid offset"); v = 0; / * keep cc happy * /} ud_asmprintf (u, "%" FMT64 "X", v) Ud_asmprintf2 (operand_asm_buf,index, "%" FMT64 "X", v);} else {int64_t v; UD_ASSERT (op- > offset! = 64); switch (op- > offset) {case 8: v = op- > lval.sbyte; break; case 16: v = op- > lval.sword; break; case 32: v = op- > lval.sdword; break; default: UD_ASSERT (! "invalid offset"); v = 0 / * keep cc happy * /} if (v
< 0) { ud_asmprintf(u, "-%" FMT64"X", -v); ud_asmprintf2(operand_asm_buf,index,"-%" FMT64"X", -v); } else if (v >0) {ud_asmprintf (u, "% s%" FMT64 "X", sign? "+": "", v); ud_asmprintf2 (operand_asm_buf,index, "% s%" FMT64 "X", sign? "+": "", v) } the repair is mainly followed by a RIP instruction to judge void ud_syn_print_mem_disp (struct ud* u, struct ud_operand * op, int sign) {UD_ASSERT (op- > offset! = 0); if (op- > base = = UD_NONE&& op- > index== UD_NONE) {uint64_t v UD_ASSERT (op- > scale = = UD_NONE&& op- > offsetters = 8); / * unsigned mem-offset * / switch (op- > offset) {case 16: v = op- > lval.uword; break; case 32: v = op- > lval.udword; break; case 64: v = op- > lval.uqword; break; default: UD_ASSERT (! "invalid offset"); v = 0 / * keep cc happy * /} if (u-> sym_resolver) {LPTSTR name = NULL; int64_t offset = 0; name = u-> sym_resolver (u, v, & offset); if (name) {if (offset) {op- > _ legacy = offset Ud_asmprintf (ujin0, _ T ("% s%") FMT64 _ T ("X"), name,offset);} else {op- > _ legacy = v; ud_asmprintf (uPower0, _ T ("% s"), name);} return }} ud_asmprintf (op- 1, _ T ("%") FMT64 _ T ("X"), v);} else {int64_tv; UD_ASSERT (op- > offset! = 64); switch (op- > offset) {case 8: v = op- > lval.sbyte; break; case 16: v = op- > lval.sword; break; case 32: v = op- > lval.sdword; break Default: UD_ASSERT (! "invalidoffset"); v = 0; / * keep cc happy * /} / / here is the addition of if (op- > base = = UD_R_RIP) {v + = (u-> inp_ctr + u-> insn_offset); if (u-> sym_resolver) {LPTSTR name = NULL; int64_toffset = 0 Name = u-> sym_resolver (u, v, & offset); if (name) {if (offset) {op- > _ legacy = offset; ud_asmprintf (uppi 0, _ T ("% s%") FMT64_T ("X"), name, offset) } else {op- > _ legacy = v; ud_asmprintf (upright 0, _ T ("% s"), name);} return;} if (v)
< 0) { ud_asmprintf(u,1, _T("-%") FMT64_T("X"),-v); } else if (v >0) {if (op- > base = = UD_R_RIP) {ud_asmprintf (uther 1, _ T ("% s%") FMT64_T ("X"), sign? _ T ("): _ T ("), v) } else {ud_asmprintf (upright 1, _ T ("% s%") FMT64_T ("X"), sign? _ T ("+"): _ T (""), v);}}
There are some other small details that are slightly different from ollydbg, so I won't repeat them here. Readers can find by themselves that after some modification and processing, we can get a disassembly engine with perfect performance and results, and some of the interfaces behind show speed performance and so on. Some debuggers will get twice the result with half the effort.
The above is the selection and modification of the disassembly engine in the ollydbg debugger. Have you learned the knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.