1

I'm trying to patch a string. So right now I'm trying to replace instruction LDSTR with LDSTR "mystring"; however, I have been unsuccessful. After assembling the LDSTR op code, I don't quite understand what comes after: a pointer address to the string or raw string bytes?

ldstr "Test";
stloc.0
ldloc.0
ret

This is what I'm trying to achieve. Thanks!

1

The opcode contains a number that is called mdToken. User-defined strings are located in Storage Stream that is called #US. You can find those while inspecting the file sections.

enter image description here

There's a great series of article on .NET assembly by Simon Coop - Anatomy of a .NET Assembly that should explain more of the internals of .NET assemblies.

1

I'd like to add a couple of comments on top of Pawel's great an concise answer.

First of all, IDA doesn't easily enable editing executables, so you should find another, more appropriate tool, for that task. In the case of replacing constant strings any decent hex editor will do the trick.

Secondly, please let me go over the different instructions, one by one:

ldstr "Test"

The ldstr instruction loads the string object in the first argument to the top of the stack.

stloc.0

The stloc instruction pops a single item from the stack and stores it in a register, according to it's index. In this case, register index 0.

ldloc.0

Similarly, ldloc stores a value from a register according to supplied index at the top of the stack. In this case, again, register indexed 0 is used.

ret

This instruction returns to the current function's caller.

As a stack based instruction-set (opposed to a register-based instruction set, for which examples are x86, arm, powerpc, etc...) the stack is frequently used of passing data around in instances where a register-based instruction set will enable register use. This is not to say you cannot use registers or stack for most functionalities in one or the other, but just that the instruction set makes it more native and natural to use either the stack of the registers.

The last paragraph is important for us to understand the nature of the provided function, which simply returns the provided string. As a stack-based instruction set, CIL's calling convention dictates that variables are returned on the stack (and not a designated register). Interestingly, this therefore implies the stloc.0 and ldloc.0 can simply be optimized out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.