flat assembler
Message board for the users of flat assembler.

Index > Windows > Rewriting code on-the-fly within existing code or data

Author
Thread Post new topic Reply to topic
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 02 Jun 2011, 18:14
I'm no fan of Windows, as I prefer to live in the world of embedded where I can do anything I want. That being said, I would like to port something I wrote over to Windows in order to teach some concepts to some new knuckleheads who think C++ can do things ASM can't...

One of the issues, I'm sure, will be the fact the code overwrites some of its own code for the sake of not having to perform some operations/comparisons and so forth. That is, it overwrites various jmps, calls and the like with new addresses or other things.

This keeps the code as speedy as possible on a little 8-bit micro already sweating bullets.

So can you point at code in a Windows program and then overwrite it? Or is it protected? Or can you layout the code in the data memory and then call/jmp to it?

(I tried to search "Data Execution Prevention" and "self-modifying code", but it appears the local search engine here doesn't support double quotes in order to search for phrases. Well, either that or I'm an idiot.)

Thanks in advance for any all comments.
Post 02 Jun 2011, 18:14
View user's profile Send private message Reply with quote
rain_storm



Joined: 05 Apr 2007
Posts: 67
Location: Ireland
rain_storm 02 Jun 2011, 19:16
You can do that, You need to define the section so that it has write and execute access...

section ".code" code readable writable executable
Post 02 Jun 2011, 19:16
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 02 Jun 2011, 20:28
On the x86 architecture, if you modify code in the same or adjacent cache line it can be a lot slower. However, modification is a simple as normal data manipulation:
Code:
@@:
; ...
self_modify:
xor edx,edx
mul eax
; ...
mov dword [self_modify],0x90909090 ; replace code
jmp @b    
Post 02 Jun 2011, 20:28
View user's profile Send private message Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 02 Jun 2011, 21:12
I know it's possible with the architecture, I was mostly concerned with how Windows might set up the various privileges on a typical task such that it would page fault if code-space was written or data-space was executed.

I think I finally found something that confirms it in Windows:
http://msdn.microsoft.com/en-us/library/ms679350%28v=VS.85%29.aspx

Thanks again for the replies, now I've got some work to do...
Post 02 Jun 2011, 21:12
View user's profile Send private message Reply with quote
ouadji



Joined: 24 Dec 2008
Posts: 1081
Location: Belgium
ouadji 02 Jun 2011, 23:14

@rain_storm
Quote:
You can do that, You need to define the section so that it has write and execute access...
section ".code" code readable writable executable
code readable writable ... It's useless to write it, this has no effect

There is no way to write in code segment.
The only way to write into code segment is to use "ds".
Any attempt to use cs will trigger a general protection exception.
Code:
mov [cs: address], xy ;whatever the type of section, this doesn't works.
    

Image

_________________
I am not young enough to know everything (Oscar Wilde)- Image
Post 02 Jun 2011, 23:14
View user's profile Send private message Send e-mail Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 02 Jun 2011, 23:33
Interesting. I thought I had read that somewhere a billion years ago.

So what do you make of the MDSN link I posted? In particular the text titled "Use in Self- and Cross-Modifying Code" ?

Or are you saying that the selector DS needs to be set with the value in the CS selector and then use DS?

Won't changing the selector be a problem? Sorry for my ignorance.


Last edited by garystampa on 02 Jun 2011, 23:36; edited 2 times in total
Post 02 Jun 2011, 23:33
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 02 Jun 2011, 23:34
Writable is still required for data write access to that section or it will raise an exception.
Post 02 Jun 2011, 23:34
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 03 Jun 2011, 00:26
garystampa, since win32/64 applications run in flat memory model, you just use DS (which is not even required to be used explicitly). ES and SS are also OK, but there is no point in using them unless the CPU instruction and/or addressing use them implicitly (like stos which uses ES and mov reg, [esp] which uses SS).
Post 03 Jun 2011, 00:26
View user's profile Send private message Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 03 Jun 2011, 01:04
Very interesting, thank you. I can avoid movs, stos, etc. But it sounds like you're saying DS and CS contain the same selector (table ptr) value.

Why is it that programmers aren't accidentally blowing holes in their code with wild pointers in range of their code? For example:

mov esi, accidental_ptr_to_code_area
mov [esi], 01234abcdh

This would overwrite code?
Post 03 Jun 2011, 01:04
View user's profile Send private message Reply with quote
Alphonso



Joined: 16 Jan 2007
Posts: 295
Alphonso 03 Jun 2011, 01:17
Code:
format PE GUI 4.0
entry start
include 'win32a.inc'

section '.text' code readable executable writable

 start:
        invoke  MessageBox,0,Mess,Tit,0
        mov     dword[Mess],'  Mo'
        invoke  MessageBox,0,Mess,Tit,0
 exit:
        invoke  ExitProcess,0

 Mess           db 'Unmodified code section.',0
 Tit            db 'Self Modifying code.',0

section '.idata' import data readable writeable

     library kernel32,'KERNEL32.DLL',\
             user32,'USER32.DLL'

             include 'api/kernel32.inc'
             include 'api/user32.inc'    
Post 03 Jun 2011, 01:17
View user's profile Send private message Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 03 Jun 2011, 01:20
I just tested it out with an old Borland C 6 Builder I have.

The DS and CS values are different on boot, but I can change DS to equal CS and then put it back - no troubles. But if I read from it, it crashes. I'll assume from Alphonso's elegant example that my CS selector is set to exec only.

I really do learn something new everyday.
Post 03 Jun 2011, 01:20
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 03 Jun 2011, 03:15
Quote:

mov esi, accidental_ptr_to_code_area
mov [esi], 01234abcdh

This would overwrite code?

In general no, since the code sections are typically set to read-only, so, although DS selector allows writing, the page table entry corresponding to the linear address has its own permissions and can still deny write access despite the selector allowed it. In Alphonso's example, such accidents would be possible (but there isn't any), since the code section is writable.

All segments (except GS and FS) have a base address of zero and a limit of 2^32-1 (or 2^64-1 for 64-bit programs), but CS is read-only. But again, the last word regarding access permissions is of the pages.

Hope I haven't messed up something in my "explanation".
Post 03 Jun 2011, 03:15
View user's profile Send private message Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 03 Jun 2011, 08:48
I thank everyone for chiming in on this - I now understand how this works. It's interesting how there's always a way around every effort to protect us from ourselves. Smile And thank goodness for that.
Post 03 Jun 2011, 08:48
View user's profile Send private message Reply with quote
me239



Joined: 06 Jan 2011
Posts: 200
me239 06 Jun 2011, 07:27
Apparently it's not

Code:
executable, code and writable, so we have to OR it with 0x00000020 (code), 0x20000000 ( executable ) and 0x80000000 ( writable ). 

or      dword ptr ds:[esi+24h],0A0000020h
    

Told you VX'ing would come in handy Razz
EDIT: May have misunderstood. I thought the question was whether or not you can modify the '.code' section and not CS.
Post 06 Jun 2011, 07:27
View user's profile Send private message Reply with quote
rain_storm



Joined: 05 Apr 2007
Posts: 67
Location: Ireland
rain_storm 07 Jun 2011, 15:34
@me239 That was also my initial understanding of the question. But I dont think everyone is talking about the same thing in this thread.

On one side people are complaining that you cannot write to memory using cs. On the other side you have people saying that the problem is the access rights that you give to each section. Two sides arguing valid points about completely different things.

@thread No-one uses cs to read / write to memory. Everyone just uses the ds and es selectors because thats what they are there for. Its the Global Descriptor Table and the Local Descriptor Table that have the final say.

You can have multiple descriptors each pointing at the exact same location in memory and each with different access rights. One descriptor may allow you to read / write the memory. Another will allow you to read / execute that same memory.

By specifying the cs selector you are forcing the CPU to use the entry that describes that memory as read / execute. If you try to write to this memory using cs then it will generate a General Protection Fault. But if you just use ds or any other selector then the CPU will use the descriptor that says the memory is read / write. And there's no problem.

http://wiki.osdev.org/GDT_Tutorial
http://wiki.osdev.org/GDT
Post 07 Jun 2011, 15:34
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 12 Jun 2011, 10:50
garystampa wrote:
in order to teach some concepts to some new knuckleheads who think C++ can do things ASM can't...
There's obviously nothing you can program in C++ that you can't do in assembly... but you can sure as hell get the job done faster and have more readable/maintainable code Smile

As for self-modifying code, I'd recommend against it - unless you do very infrequent modifications (like choosing optimal codepaths at program start), your code will end up slower on modern CPUs, not to mention you're abolishing memory protection and run the risk of anti-malware apps going apeshit.

Instead of setting your PE code sections as writable, you can use VirtualProtect to temporarily have write capability. If you think two kernel calls (protect-off and protect-on) are too expensive, you're modifying the code section too often.

Don't try to build executable code on the stack (or heap), newer Windows versions protect against this - and with good reason, since it's one of the major buffer overflow attack vectors. If you do dynamically generated code, stick it in VirtualAlloc'ed buffers.
Post 12 Jun 2011, 10:50
View user's profile Send private message Visit poster's website Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 14 Jun 2011, 12:59
Thanks for your input. Obviously all of the things you stated are true in a PC-centric world.

As I stated at the start - the code is running on 8-bit micros we use in several of our embedded applications. These "knuckleheads" are very PC-centric: they see the world as a PC.

My experience has shown when they finally wake up from that funk they'll thoroughly enjoy what true programming is. But it takes some examples - on a PC...
Post 14 Jun 2011, 12:59
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 14 Jun 2011, 16:53
Well, there's a big difference between running on a PC and running on a microcontroller - trying to impose constraints (or the lack of Smile) from one platform on other other is obviously going to be a big cup of fail - goes both ways.
Post 14 Jun 2011, 16:53
View user's profile Send private message Visit poster's website Reply with quote
garystampa



Joined: 25 May 2011
Posts: 52
Location: Central FLorida
garystampa 18 Jun 2011, 23:25
The examples went fine and they are actually understanding more programming at the metal - and its benefits.

I always enjoy seeing high-level programmers suddenly gain an awe and appreciation for assembler.

They have left "knucklehead" status and are now officially "indoctrinated".
Post 18 Jun 2011, 23:25
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.