Multiline Ultimate Assembler (an OllyDbg plugin)

Multiline Ultimate Assembler is a multiline (and ultimate) assembler (and disassembler) plugin for OllyDbg. It’s a perfect tool for modifying and extending a compiled executable functionality, writing code caves, etc.

rar multiasm.rar (379.67 kB, changelog)

Posted in Releases, Software by RaMMicHaeL at September 13th, 2009.
Tags: ,

120 Responses to “Multiline Ultimate Assembler (an OllyDbg plugin)”

  1. Ange says:

    i really like that plugin, but sometimes for no reason, it doesn’t want to accept strings – the example like on this page wouldn’t work, it would give me a ‘command mnemonic expected’ in the middle of “hello world” string.

  2. Ange says:

    just ignore previous comment, i didn’t see i don’t have the latest version :)

  3. totalgame says:

    How do i plugin on ollydbg? I’ve put the plugin in plugin folder but it doesn’t appear on olly. Should i set something on ollydbg.ini? -Thnx- nice blog

  4. Joe McKenzie says:

    AWESOME!! This plugin would’ve saved me a lot of time on multiple occasions.

  5. Morten says:

    Very useful. But it crashes almost everytime.

    It writes the opcodes just fine, but then crashes Olly a few seconds later.

    • Morten says:

      Okay, I’ve pinpointed it to Labels.

      If “Write Labels” is enabled in options, it crashes me Ollydbg (1.10 – Tried clean install too).

      If I untick “Write Labels” it works just fine.

      • Morten says:

        PS: I can’t get it to support labels for loop instructions (LOOP, LOOPD, LOOPE).

        @Bla:
        LOOP @Bla ; does not work
        LOOP 00401000; works

      • RaMMicHaeL says:

        I’ve never experienced such crashes. You say it happens with any code/binary even on a clean olly? Can you say on which RVA it crashes?

      • RaMMicHaeL says:

        After a number of experiments, I was able to reproduce the issue. Seems like it’s a bug of Ollydbg and it’s Quickinsertname/Mergequicknames functions. Maybe Ollydbg does not expect these functions to be called from another thread – what MUltimate Assembler does.

        It does not crash on my PC while assembling a sane amount of code, but inserting labels/comments in a loop make it eventually crash.
        Perhaps your PC is faster, and thus it happens regularly for you.

        Disabling “Write Labels” and “Write Comments” will help, but if you find these useful, you could make MUltimate Assembler use Insertname instead of Quickinsertname/Mergequicknames (Insertname accepts the same parameters as Quickinsertname). As an Ollydbg user it should not be difficult for you :) Try it and tell me how it works.

      • RaMMicHaeL says:

        The crash was fixed in v1.3

  6. RaMMicHaeL says:

    Updated to v1.2.1

    Bug fixes:
    - Now correctly assembles loop instructions with labels (reported by Morten).
    - Fixed assembling short jumps with labels on high addresses.

  7. RaMMicHaeL says:

    Updated to v1.2.2, which only creates a single thread on startup and uses it instead of creating a new thread every time the assembler window is opened.
    That makes it work together with the phantOm plugin.

  8. MCKSys Argentina says:

    Great Plugin!!

    Thanks!

  9. MFan says:

    Thanks for the update. Disassembler is awesome! Still waiting for tab renaming feature, though. :)

  10. Apuromafo says:

    nice plugin as say MCKSys Argentina ,, i use from version 1,

    ask: is posible do this same for ollydbg 2 ( now was a update and cann add plugin ^^)

    BR, Apuromafo

  11. tuk says:

    this is my fav olly plugin, not to seem ungrateful but I think it will take some time for the plugin documentation to appear..and its a real pain having to juggle multiple versions of olly ..as v2.0 is the best now even tho a little buggy

    thanks for your work

  12. RaMMicHaeL says:

    v1.7.1:
    * Search/replace in editor (hotkeys: Ctrl+F, Ctrl+H, F3, Shift+F3).
    * Fix: Correctly handle prefixed instructions (LOCK, REP, REPE/REPZ, REPNE/REPNZ).

  13. R4ndom says:

    Just came across your amazing plugin. It is a life-saver. I am doing a tutorial on code caves right now and I can’t wait to introduce your plugin to my many readers.

    I have one feature request. Seeing as a lot of the members on my site are beginners, it would be great if, instead of just giving a generic error, your plugin said what line number the error was on or highlight the line or something. I can already tell I’m going to get numerous questions like “Can you look at my code? It says I have a ___ error but I can’t figure out where”.

    Anyway, if you have the time. If not, it’s still an amazing plugin and I will use it often.

    I am also going to ask my minions to donate to your cause, as I plan to do as well. Too few people get recognized for their hard work.

    -R4ndom

  14. R4ndom says:

    btw: do you have any sort of manual or quick guide or anything? I would love to include something in the tutorial…

  15. VEG says:

    Может быть вам стоит рассказать об этой штуке на Хабрахабре? Там очень большая аудитория, и статьи на подобную тематику воспринимаются очень тепло. Пример: http://habrahabr.ru/post/51857/

    Также вы можете рассказать о 7TT, рассказав для примера как вы делали какую-нибудь простую функцию (чтобы не посчитали рекламой и воодушевить других программистов). Это будет просто бомба! :) Ну и +10 к популярности вашего ПО. Для примера, моя последняя статья ( http://habrahabr.ru/post/168269/ ) за 10 часов уже собрала больше 25000 просмотров — а это немало.

    Страна должна знать своих героев! :) Если надумаете что-нибудь написать и оценить Хабраэффект, я могу поделиться инвайтом.

    • RaMMicHaeL says:

      Может быть, хотя не уверен, что из меня выйдет хороший писатель. Да и время для этого найти нужно.

      А вообще я с Хабром знаком, почитываю иногда.
      Про 7TT, кстати, кто-то уже писал (кратко, но все же):
      http://habrahabr.ru/links/125911/

      Ну а так, если надумаю писать, буду знать к кому обращаться за инвайтом. Спасибо за предложение :)

      • VEG says:

        Это не считается, поскольку заметка даже на главную не попала. Секрет успеха на хабре — немножко подробностей, как оно работает. А там где вы показали кроме ссылки ничего нет.

        Что касается написания статей. Нужно просто написать пару первых предложений — остальное уже как-то само получается :)

    • RaMMicHaeL says:

      Также вы можете рассказать о 7TT, рассказав для примера как вы делали какую-нибудь простую функцию

      Вот, накатал статейку:
      Здесь была ссылка

      Ваше мнение?

  16. Mr. eXoDia says:

    Hi,

    Would it be possible to also compile this plugin as a standalone DLL/static library? This would help with writing tools that need to inject code for example.

    Please consider it.

    Greetings,

    Mr. eXoDia

    • RaMMicHaeL says:

      Hi Mr. eXoDia,

      The plugin uses OllyDbg’s assembling and disassembling API, so it can’t be made standalone. Have you considered using FASM or similar?

      RaMMicHaeL.

      • Mr. eXoDia says:

        Thanks for the reply! Yes I considered fasm, but your plugin just rocks..

        And does your plugin only rely on this library or also on other parts of olly (only a dll that assembles is good enough) because disasm is open source: http://ollydbg.de/srcdescr.htm

        Greetings

        • RaMMicHaeL says:

          Here are the functions it imports from Olly:
          Addtolist
          Pluginreadstringfromini
          Findmemory
          Findmodule
          Finddecode
          Pluginreadintfromini
          Readmemory
          Disasm
          Assemble
          Dumpbackup
          Plugingetvalue
          Getstatus
          Findsymbolicname
          Pluginwriteinttoini
          Writememory
          Quickinsertname
          Pluginwritestringtoini
          Mergequicknames
          Deletenamerange
          Findname

          So no, not much
          But it’s designed to assemble code to memory. You want a standalone library to write code to a file, right? If so, the division to sections (<401000> stuff) would either dropped, or I’d have to use a custom file format or something.

          In any case, how would that be better than FASM?
          In addition, FASM supports macros, which are very powerful and might come in handy.

          P.S.

          your plugin just rocks..

          Thanks :)

          • Mr. eXoDia says:

            the sections () would not be used with my code.. It’s more like this:

            unsigned int makeinline(unsigned char* result, char* assembly, unsigned int va_base)

            result is the resulting assembly code
            assembly is just the plain text code (with @label, “\x03″ support)
            va_base is the virtual address where the result will be written later on

            return value is the length of the resulting buffer.

            For me it’s more about the simple syntax and compatibility with the odbg version of multimate assembler.

            Something optional would be that the function also returns a relocation table, but for me it’s mainly about the code style.

            Greetings

            • RaMMicHaeL says:

              Let’s make a deal :)

              I make the standalone library you requested, and you write an article about how you use it, what it’s good for, etc.
              I’ll post your article on my blog, so others can see what it’s all about, and maybe use it too.

              What do you think?

  17. Morten says:

    Hello again.

    I’ve been trying to get it to work with ollydbg 2. I’ve downloaded the latest version and placed multiasm_odbg2.dll in ollydbg2\Plugins, and set up the plugin directory in the ollydbg options.

    However, the Plugins menu is grayed out, and the plugin doesn’t seem to load at all.

    Reading on ollydbg2.de it seems he changed the plugin interface, so I guess it’s incompatible with the new version.

    Any chance of an update for the latest version of ollydbg2?

    Thanks.

    • Morten says:

      Hmm, downloaded the second latest version of olly, and now it works. Guess I’ll just stick with that one for now.

    • RaMMicHaeL says:

      Hi,

      The latest version, v2.1.1, is compatible with the latest version of OllyDbg, odbg201h.zip (November 19, 2012). Just rechecked it.
      Could it be that you’re trying an older version of the plugin?

      • Morten says:

        Hmm. Weird. It works now. I redownloaded olly 201h and MUA v2.1.1 from the top of the page.

        Though I’m certain that it’s the same versions I used before. Perhaps it’s some ollydbg settings. I’ll poke around.

        Thanks.

  18. Mr. eXoDia says:

    Hey,

    I’ve been busy with this standalone library, but currently real life stuff is eating all my time… I’ll continue writing the tutorial, but it might take more time.

    Greetings

  19. Mr. eXoDia says:

    Hey,

    So I had some time to ‘finish’ this coding example of your library so here it is: http://rghost.net/private/45983365/f6fdd54ba9db02e63867bf1fe66ab2c7 I still need to write a full tutorial in PDF format, but here is just what I could do by now (it works, tested on one target, but it works)

    Greetings,

    Mr. eXoDia

    • RaMMicHaeL says:

      Nice :)

      The technique mostly targets protectors, right?

      I found a bug that caused it to crash on my PC, pefunc.cpp line 70:

      psh=(IMAGE_SECTION_HEADER*)(&pnth->OptionalHeader)+pnth->FileHeader.SizeOfOptionalHeader;

      The pointer is not calculated correctly.

      Also, it might be worth creating the extra section automatically.

      • Mr. eXoDia says:

        Yes I think mostly for targeting protectors. But it could also be useful if someone wants to make a small disassembler with easy multiline assembling feature (although x64 would be better in that case).

        Thanks, I reused the code from another project and it isn’t really used so I experienced no crashes. Fixing line:
        psh=(IMAGE_SECTION_HEADER*)((DWORD)(pnth)+pnth->FileHeader.SizeOfOptionalHeader+sizeof(IMAGE_FILE_HEADER)+sizeof(DWORD));

        I will see if I’m going to implement this feature.. usually I use titanengine, but in this case I would need to write this code by myself (no problem, but it takes time).

        Greetings,

        Mr. eXoDia

  20. Mr. eXoDia says:

    Hi,

    Lately I was using multimate asm to do some relative coding in DLLs, but would it be possible to add a syntax for the module that you’re currently debugging?

    Greetings

  21. adoxa says:

    After using this plugin for a while to patch a program, I’ve noticed some things.

    Some sort of align directive would be useful, allowing jump tables or floating point constants to automatically go to dword boundaries.

    Some sort of “stop” directive might be nice, too. Something like:

    some instructions
    !stop ; if you get here, there’s too many instructions

    The editor doesn’t like undoing in overwrite mode. For example, type in “ab”, turn on overwrite, go back and delete the “a”, undo and “a” replaces “b”.

    A keyboard shortcut (Ctrl+D perhaps) to put the debugger back into focus would be really nice.

    • RaMMicHaeL says:

      Thanks for the feedback.

      Some sort of align directive would be useful, allowing jump tables or floating point constants to automatically go to dword boundaries.

      I guess it can be useful sometimes, but It will complicate the syntax, and I’m not sure it’s worth it.

      I remember somebody suggested a “bp” pseudo instruction, which will put a breakpoint on the following command. Perhaps something similar to C’s “pragma” directive is worth considering.

      !stop ; if you get here, there’s too many instructions

      How will it know when there are too many instructions?
      It might work like this, maybe:
      !max_address(00401020)
      I think it might be a candidate for a pragma-like directive as well.

      The editor doesn’t like undoing in overwrite mode. For example, type in “ab”, turn on overwrite, go back and delete the “a”, undo and “a” replaces “b”.

      I’m not the author of the editor component. I’m using RAEdit. You’re welcome to fix this and send me a pull request:
      https://github.com/RaMMicHaeL/SimEd

      A keyboard shortcut (Ctrl+D perhaps) to put the debugger back into focus would be really nice.

      That should be easy.

      • adoxa says:

        I guess it can be useful sometimes, but It will complicate the syntax, and I’m not sure it’s worth it.

        How about as an extension to the label format: @label@align: would create @label as a multiple of align bytes?

        How will it know when there are too many instructions?

        Yeah, sorry, my example didn’t format right and there was no edit; I’ll try again.
        <start>
        some instructions
        !stop

        So stop is an address, not the literal word.

        You’re welcome to fix this and send me a pull request

        Done.

    • adoxa says:

      How will it know when there are too many instructions?

      Since you use a tag-like format for the address, how about this:
      <start>
      instructions
      </stop>

    • RaMMicHaeL says:

      I’ve just released v2.1.4, which fixes the editor bug (thanks for the fix!) and implements Ctrl+D.
      As for the other two suggestions: I’ll add them to my TODO list :)

      • adoxa says:

        Yeah, that key’s much better than having to click the mouse or double Alt+Tab. But the undo fix has introduced another problem: you’ve spelt my moniker backwards in the changelog. :)

        • RaMMicHaeL says:

          Oops, sorry for that. It will be fixed in the next version, unless you want me to release one just with the moniker fix.

          About the align/stop suggestions, I thought about it some more, and here’s what I think:

          I don’t like your suggestion of including aligning in the label (@label@align:). Labels are just names, and IMO shouldn’t imply any data write/manipulation.

          Your suggestion of the stop address (</stop>) is nice, but I thought it would be better to generalize such extras into a pragma-like thing, like I mentioned earlier.

          Such commands could begin with ‘!’. Examples:


          <00401000>

          nop ; 00401000

          !align 4 ; Fills the three bytes with zeroes
          nop ; 00401004

          !align 4 FF ; Extra param, fills the three bytes with FF
          nop ; 00401008

          ; ...

          <00402000>

          nop ; 00402000

          !assert_addr_na 00402001 ; OK

          <00402000>

          nop ; 00402000
          nop ; 00402001

          !assert_addr_na 00402001 ; Error

          I don’t really like the “assert_addr_na” (na – not above) name too much, but I couldn’t think of something both short and descriptive. Ideas are welcome :)

          • adoxa says:

            Oops, sorry for that. It will be fixed in the next version, unless you want me to release one just with the moniker fix.

            No, it can wait.

            I don’t like your suggestion of including aligning in the label (@label@align:). Labels are just names, and IMO shouldn’t imply any data write/manipulation.

            Fair enough, but it would have made dword-aligned strings much nicer to write.

            @str1@4: "string 1"
            @str2@4: "string 2"

            versus

            !align 4
            @str1: "string 1"
            !align 4
            @str2: "string 2"

            I don’t really like the “assert_addr_na” (na – not above) name too much, but I couldn’t think of something both short and descriptive.

            Would an expression work, making assert a bit more general?

            >402000>
            nop
            nop
            !assert addr <= 402001

            Something else that would be useful is an enhancement to anonymous labels, where each additional @ skips another label.

            je @@f ; jumps to second anonymous label
            ...
            jne @f ; jumps to first
            ...
            @@: ; jne goes here
            ...
            @@: ; je goes here

            • RaMMicHaeL says:

              Fair enough, but it would have made dword-aligned strings much nicer to write.

              I think making !align 4 available, and making @label@4: a syntax sugar of it, with the note that it’s just a convenience and the two are not really related, is OK.

              Would an expression work, making assert a bit more general?

              I thought about it too, but first, it needs to be implemented. Second, is it needed at all?
              What else is there to assert about besides addr? And why would you use an operator other than “<=”?

              Something else that would be useful is an enhancement to anonymous labels, where each additional @ skips another label.

              Is it worth the complexity? Why not just use a named label?
              Is there an assembler which uses this syntax?

              • adoxa says:

                What else is there to assert about besides addr? And why would you use an operator other than “< =”?

                Okay, maybe approach it a little differently: !stop_at 402001 Ideally that would restore from where it started and tell you how far it went beyond the stop address (which is what it implies, whereas the assert just implies a warning and it’s up to you to find out how far it went and restore it).

                Is it worth the complexity?
                It would be for me. You could always make things simple for yourself and send me the source…

                Why not just use a named label?
                Because then I have to think of a name. And it’ll show up in OllyDbg.

                Is there an assembler which uses this syntax?
                I just saw it recently, but don’t remember where. It was done with macros, possibly with fasm.

                • adoxa says:

                  Yet another approach would be to turn the address into a range: <402000-402001>.

                • RaMMicHaeL says:

                  Okay, maybe approach it a little differently: !stop_at 402001

                  I don’t see how it’s different than !assert_addr_na, except the name. There’s no reason why the assert can’t show you an informative message, and move the caret to its location.
                  I don’t like the stop/stop_at names, as they are not descriptive. If you’d browse an asm source and see a “stop” command, I assume you’ll get confused.

                  You could always make things simple for yourself and send me the source…

                  Heh, I’ll keep that in mind :)

                  It was done with macros, possibly with fasm.

                  Well, macros are macros. Not all the things they allow you to do are useful.

                  • adoxa says:

                    I now like the range idea best, as that lets the assembler know ahead of time where it should stop. I’d say it’s also very similar to what you already do with the end-of-section, as I recently discovered.

                    If you really want to be descriptive, maybe it should be “Multiline not-as-Ultimate-as-all-that Assembler.” ;)

                    • RaMMicHaeL says:

                      You’re talking about this message, right?

                      End of code block exceeds end of memory block (2 extra bytes)

                      There’s nothing about “know[ing] ahead of time where it should stop” here. It just assembles the block, and then does the check. Otherwise, it wouldn’t be able to say how many extra bytes you have.

                      Perhaps the range syntax is indeed the better one, but I don’t like the fact that it uses ‘-’, which could be interpreted as a minus. Perhaps it could look like this:
                      <00401FFE..00401FFF>

                      If you really want to be descriptive, maybe it should be “Multiline not-as-Ultimate-as-all-that Assembler.” ;)

                      It’s all relative. It’s not as flexible as e.g. FASM is, but it surely is ultimate comparing to what you have built in OllyDbg :)

                    • adoxa says:

                      Perhaps it could look like this:
                      <00401FFE..00401FFF>

                      That would be great.

    • RaMMicHaeL says:

      Some sort of align directive would be useful, allowing jump tables or floating point constants to automatically go to dword boundaries.

      Some sort of “stop” directive might be nice, too. Something like:

      some instructions
      !stop ; if you get here, there’s too many instructions

      you’ve spelt my moniker backwards in the changelog.

      I’ve implemented/fixed those in v2.2.
      I did not do extensive testing, so please, try to feed the assembler with various invalid input and see whether it always works as expected. Tell me if it doesn’t. Thanks :)

      • adoxa says:

        Excellent, I’ll rearrange stuff again to take advantage of it and let you know how it goes. Now I can remove all those extra \0-s I’ve added to my strings (but to free up space in the code section, I’ve moved jump tables and float constants to padding at the end of .rdata, so with aligned strings everything else is already aligned).

      • adoxa says:

        It seems @label@align: still assigns the pre-aligned address to @label.

      • adoxa says:

        The range is working a treat, although I keep getting caught out. E.g. it says two bytes over, so I tweak it, but then it says three bytes over – argh, look where the cursor is!

        If I may make one more suggestion, perhaps recognise jmp @e (e for end) and if it doesn’t fit, just nop it instead.

        • RaMMicHaeL says:

          E.g. it says two bytes over, so I tweak it, but then it says three bytes over – argh, look where the cursor is!

          I’m not sure I understand. Can you provide an example?

          If I may make one more suggestion, perhaps recognise jmp @e (e for end) and if it doesn’t fit, just nop it instead.

          What I think might be a better idea is filling the unused bytes of the block with NOPs.
          I need to think about a good syntax for it, though.

          • adoxa says:

            You place the cursor on the instruction that goes over, but I only look at that the second time. :) So given pop esi/ret 4, you’d tell me it’s one byte over (and leave the cursor on the pop), I’ll save one byte and now it’s three bytes over (with the cursor on the ret 4, which now I notice.) That’s just my misunderstanding with how I want it to work and how it actually works.

            As for NOP‘ing blocks, how about !pad [90] – 90 being the NOP opcode by default, but could also allow 0CC, or 00 for data areas. Or maybe !fill.

        • RaMMicHaeL says:

          Oh, so you just want @e to be a special label that refers to the address after the last command of the block, right? Seems like I’ve misunderstood your suggestion. It seemed to me like you’re suggesting some kind of special case command jmp @e, according to:

          and if it doesn’t fit, just nop it instead.

          I thought about another improvement, which may help here too, but is much more generic: implementing local labels. You could perfix the label with e.g. a dot, and it would apply only for the current block. For example:

          <00401000>
          
              jmp @.e ; jump below
              nop
          @.e:
          
          <00401010>
          
              jmp @.e ; jump below
              nop
          @.e:
          
          <00401020>
          
              push @.e ; error, label is not defined
          

          Perhaps a better syntax can be introduced. I have to think about it.

          • adoxa says:

            No, you were right the first time – ideally I want the label (so it can also be used with conditional jumps) and a NOPable jump (to continue from the end of the block).

            ; patched code is smaller than original
            <401000..401010>
                jmp @e ;; jmp 401010 - skip remainder
            
            ; patched code is one byte smaller than original
            <401100..401101>
                jmp @e ;; nop - all that's needed
            
            ; patched code is same size as original
            <401200..401200>
                jmp @e ;; nothing at all - already there
            

            Local labels would be good, too (but they wouldn’t help with the above, since that effectively wants to jump outside the block). My preference would be either @@local (MASM/TASM default) or, if feasible, just .local (NASM/FASM, which actually append to the previous global, so still accessible as @global.local, if you really want to be fancy).

  22. adoxa says:

    I’ve come across an “Internal error”. I was using unused .data for some variables, some of which I had initialized. I then remembered that that part of .data is really virtual, so I split it into two, placing the initialized stuff back in .text (as I’ll be writing it all back to the exe). To compensate I wanted to add the difference of the pointers: push [dword ecx+@textvar-@datavar]. It’ll do the +@textvar or the -@datavar, but not both (OllyDbg itself assembles it).

    • RaMMicHaeL says:

      That’s an interesting issue, caused by a kind of a hack I use.
      Consider the following example:

      <00401000>
          jmp @next
          ; more code
      @next:
      

      When doing the first pass on the code, you see “jmp @next”, but you don’t yet know what @next is. It might result in a long jump or a short jump. But you have to know the length of the jmp command in bytes, in order to be able to calculate @next.

      What I do on the first pass is replacing any label with the address of the command plus INT_MAX. So “jmp @next” gets assembled as “jmp 80400FFF”, making it a long jump. Then I know it’s going to be 5 bytes long, and I can proceed to the next commands.

      On the second pass, when I know what @next is, I can assemble the real jmp command, which will always be long, whatever @next is.

      With your code, gets assembled in the first pass as:
      push [dword ecx+(addr+INT_MAX)-(addr+INT_MAX)]
      Which results in:
      push [dword ecx+0]
      The zero is discarded and the command length becomes smaller than it needs to be. That’s why there’s an error on the second pass.

      There are other possible issues with this hack technique, for example:

      <80000001>
      	PUSH @a
      
      <00401000>
      @a:
      

      But the code range of 80000000 +- FF is rare enough that nobody have noticed.

      I need to think about it. One solution can be to replace every constant which is set by a label with a literal which fits only in a DWORD, -and- the difference between it and the current address also fits only in a DWORD. I don’t think OllyDbg is flexible enough to handle it.

      Ideas are welcome :)

      • adoxa says:

        I had a look at how Playtime handles it and it turns out it doesn’t – not only does it barf when you give it two labels, a single label is generated incorrectly.

        In my case, performing the substitution on the first pass would be sufficient (@datavar is defined before the push). Otherwise, maybe you could use a variable to store the offset, then reset it once it’s been used.

        int label_offset = INT_MAX;
        // …
        if (label) {
        offset = addr + label_offset;
        label_offset = 0;
        }

        The other option is to ask Olly to use (rather than ignore) the LARGE keyword to actually assemble the long form.

        • RaMMicHaeL says:

          I had a look at how Playtime handles it and it turns out it doesn’t – not only does it barf when you give it two labels, a single label is generated incorrectly.

          Do you mean this?
          http://code.google.com/p/ollydbg2-playtime/

          I’m not familiar with it (and I don’t really know Lua). What relevant functionality does it have?

          In my case, performing the substitution on the first pass would be sufficient (@datavar is defined before the push).

          Yeah, but it must not be the case. The two labels could be defined below.

          maybe you could use a variable to store the offset, then reset it once it’s been used.

          Do you mean for every command?
          If I understand your suggestion correctly, this:
          mov dword [@L1], @L2
          will turn to this:
          mov dword [(addr+INT_MAX)], (addr)

          which might result in a short form. Also, you can still get a case where it fails, e.g.:
          mov dword [(INT_MAX+addr_of_L1)-@L1], 1

          With this approach, it’s all about probability.

          The other option is to ask Olly to use (rather than ignore) the LARGE keyword to actually assemble the long form.

          I’m not sure it has such a feature. Also, how could I get the difference between e.g.:
          mov dword @L1, 401000
          and:
          mov dword [401000], @L1

          Meanwhile, try this one:
          https://www.dropbox.com/s/ddpvvrmmndf9vzi/multiasm_v2.2.3.2.rar?dl=1
          It has some improvement to the hackfix. Not perfect, but should work for your case.

          • adoxa says:

            I’m not familiar with it (and I don’t really know Lua). What relevant functionality does it have?

            I’m not all that familiar with it either (nor do I really know Lua); I just knew it had an assembler, with labels, so I tried it out to see what would happen.

            If I understand your suggestion correctly, this:
            mov dword [@L1], @L2
            will turn to this:
            mov dword [(addr+INT_MAX)], (addr)

            Well, that depends where you put the initializer. :) But then, isn’t that okay anyway? No one’s going to generate code between -80..7F, so just using addr itself should be fine.

            Also, you can still get a case where it fails, e.g.:
            mov dword [(INT_MAX+addr_of_L1)-@L1], 1

            I don’t follow what you’re trying to say. If you already know the address of L1, why are you still adding INT_MAX? And @L1-@L1 really should be zero, anyway.

            Meanwhile, try this one. It has some improvement to the hackfix. Not perfect, but should work for your case.

            Indeed it does, thank you.

            • RaMMicHaeL says:

              But then, isn’t that okay anyway? No one’s going to generate code between -80..7F, so just using addr itself should be fine.

              Yes, unless the command interprets the literal as a relative address. I’m not familiar with a command which contains two literals, and one/both of them is relative, but maybe there is one.

              I don’t follow what you’re trying to say. If you already know the address of L1, why are you still adding INT_MAX? And @L1-@L1 really should be zero, anyway.

              I meant the address of the command, not of @L1. Say, if the address of the command is 400000, and you write [803FFFFF-@L1], it will become zero on the first pass, and non-zero on the second pass. The point is, whatever delta I choose, there’s always a range which will result in an error. To fix it properly, I’ll need to actually parse the command and understand the role of the labeled constants.

              Indeed it does, thank you.

              Great. This one just adds extra 0×11111111 to every label.

  23. adoxa says:

    If you were at all curious, here is what I was working on. (As it turns out, I rearranged stuff again, so ended up not using !pad; could have used @e, though.)

    • RaMMicHaeL says:

      Yes, I was curious, and in fact I was about to ask you :)

      The amount of code looks impressive. Seems like you’ve put quite a bit of effort into it. I did something similar with Resouce Hacker here.

      Have you considered writing an article about it? I’ll happily publish it on my blog, if you’d like.

      could have used @e, though.

      What makes it more useful than !pad? It also turns into a nop if the jump command doesn’t fit.

      • adoxa says:

        I did something similar with Resouce Hacker here.

        That reminds me…

        Have you considered writing an article about it?

        It’s bad enough writing a doc, I don’t wanna be writing more.

        What makes it more useful than !pad?

        @e just avoids having to type in the end address again. :) It depends how you want to use it, I guess. There were only two places where I thought the patched code might be about the same size (one was one byte smaller, the other exact length; but both these cases ended up becoming redundant and I just changed a pointer, instead); every other place I was pretty sure was going to be smaller, so jumping out was assumed and padding was not necessary. BTW, adding the end address to the disassembler might be nice (perhaps as an option).

  24. Valentin says:

    На протяжении длительного времени я использую в работе этот прекрасный инструмент. Но обратил внимание на следующее. Первые несколько запусков плагин работает очень быстро, а затем начинает тормозить (начинает медленно открывать окно, долго выполняет захват выделенного кода, и т.д.). Такое ощущение, что он начинает (после нескольких запусков) усиленно поедать ресурсы, и, при этом тормозит не только сам плагин, но и отладчик OllyDbg. Приходится перезапускать отладчик, после чего плагин опять начинает быстро работать. Нельзя ли предусмотреть принудительную очистку памяти после закрытия плагина?

    • RaMMicHaeL says:

      Ни разу не сталкивался с подобной проблемой.
      Есть признаки кроме тормозов? Память, CPU?
      Почему Вы решили, что проблема в Multiline Ultimate Assembler, а не в другом плагине, например?

      • adoxa says:

        I had a similar problem. Initially, it would assemble instantly (well, that’s how I remembered it, anyway). I then exited, deleted OllyMoreMenu 1.5 (I never used it and it interfered with Ctrl+O), restarted and it would take 19 seconds to assemble. I couldn’t put OllyMoreMenu back on, as I didn’t have a backup and couldn’t find it again, only 1.5+, which instantly crashed. It somehow resolved itself and now takes about 3 seconds to assemble (the somewhat bigger final version), although sometimes it was about 10 seconds (possibly with a “Not responding” message). Testing just now takes about 6 seconds.

        • RaMMicHaeL says:

          The amount of time it takes to assemble is not the same issue as interface sluggishness (delay upon opening a window, upon disassembling, etc., which is what Valentin reports). Of course, this issue is not less important. I’ve never felt that it’s too slow, but on the other hand, I’ve never worked with files as large as e.g. your 2000-liner. I’ll experiment with large files and will see what causes the delay.

  25. adoxa says:

    Another thing that might be nice to have is the ability to split regions. For example, adding entries to jump tables, putting the new tables in unused space in .rdata.

    <401000> jmp dword[eax*4+@table1]
    <rdata=402000> ;; create an alias for this region
    @table1:
        dd @addr1_0
        dd @addr1_1
    
    <401100> jmp dword[eax*4+@table2]
    <rdata>    ;; continue where it left off
    @table2:   ;; so this is at 402008
        dd @addr2_0
        dd @addr2_1
    

    That allows keeping related code & data together in the editor, even though they’re separate in memory.

Leave a Reply