Ninho
11.12.2009, 00:17 |
new HACKWRAP fix for MS-DOS7+, aka smashing the bug (Miscellaneous) |
Been busy trying my newborn idea for a definitively better HACKWRAP, and Guys! is it cool !!!
You'll be delighted to learn that it doesn't cost ONE byte !
The way this apparently impossible yet simple prodigy is going to work without disturbing Win-DOS's fragile equilibrium is simple yet elegant (small+simple==beautiful, almost always)
- There is a byte in MS-DOS 7+ data segment, call it Win386Flags, of which MS uses three bits as 3 flags related to DOS/Win interaction. The other bits are unused and we can be pretty sure they'll stay available in eternity :)
- The byte is checked at many places in the Kernel and modified in several more, but they did it properly whether by chance or thru art, using TEST/AND/OR instructions that never touch unassigned bits. So, then :
- I pick an unused bit in the SAME byte for a new flag which HACKWRAP, or dare I say FIXDOS ;=) will set during of Config.sys. An other instance of HACKWRAP, or a companion program will later unset the flag, restoring the usual DOS working (an oxymoron?)
- We need be concerned by just 1 TEST instruction in the DOS Kernel ! When doing an int 21/AH=31 "go TSR", it checks Win386.bit_zero and, if that bit of theirs is 1, meaning Windows is running in "386 enhanced" mode, then they correctly SKIP over the TSR bookkeeping.
So, what FIXDOS/HACKWRAP does is we'll FLIP one bit in that instruction, in memory, that will change it to TESTing for both OUR new bit and THEIRS and the following JNZ will take the proper action in all cases, skipping over the bookkeeping whenever it is unwanted !
- Of course I've checked all the other uses of the byte I'm going to "hijack", this should not harm anything else and all should work smoothly afterwards. The method doesn't even require us to flip back the instruction bit when we're done loading TSRs from Config.sys, although we might do it for a supplement of tranquility...
I'm not going to make the speech longer, for fear it would be longer than the actual program...
I did first tests "by hand" today (in Bochs), now back to proper programming and we'll have something neat to test together.
But I didn't want to delay a short description of what we're going to do, and I'm confident it'll work out neatly. Comments very welcome of course ! --- Ninho |
ecm
Düsseldorf, Germany, 11.12.2009, 15:02
@ Ninho
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
Sounds like a neat kernel code hack. How do you find the DOS code segment? How do you locate the instruction that has to be patched?
If you release the program (hopefully generally including the source), could you document the DOS data segment items that you found to be used by MS-DOS? I'm just interested. --- l |
Ninho
12.12.2009, 01:12 (edited by Ninho, 12.12.2009, 10:08)
@ ecm
|
new *FIXWRAP* for MS-DOS7+, aka smashing the bug |
> Sounds like a neat kernel code hack. How do you find the DOS code segment?
> How do you locate the instruction that has to be patched?
>
> If you release the program (hopefully generally including the source),
> could you document the DOS data segment items that you found to be used by
> MS-DOS? I'm just interested.
Sure. I'll empty my bag of tricks. But not now, I must take some rest.
When I was working, I mean, when I was paid for working, I never had such a hard work day. That I remember, at least
And the wife won't tolerate it much longer, either...
--
Ninho
thread title has been updated. |
Ninho
12.12.2009, 16:05 (edited by Ninho, 13.12.2009, 11:14)
@ Ninho
|
FIXWRAP technical thread. News |
Coding is in progress. This new fix is without contest simpler and better than HACKWRAP was, the flip side is that whereas setting up Hackwrap was quick and easy, setting-up FIXWrap is much more complicated to do it properly.
The code is already several hundred tightly coded ASM instructions, a size at which notepad ceases to be an ideal programming tool and one starts to consider introducing macros and more "modularising" of the code. The brain still spits out code but overheating is a threat.
I think I'm past half the hardcore part and may avoid having to load heavy programmer's "aids". Rather, I will debug the code in a bochs as it progresses, with the help of a couple macros that should help me to stay in command.
Expect something for you all to test run in a few days, surely not the final but rather stuff that will allow us to check details on all MS-DOS versions and configurations of interest. --- Ninho |
Ninho
12.12.2009, 18:22 (edited by Ninho, 12.12.2009, 19:26)
@ Ninho
|
CM's questions, answered |
Moving the technical questions to this thread
CM asked :
1 > How do you find the DOS code segment?
There are more than one roads. I try to choose the quickest yet secure one.
Here's my pick. Once we've asserted we are under a true MSWinDOS 7/8, as discussed in earlier exchanges :
- Case DOS 8 (checked the version of IO.SYS for floppies, since the regular one does not even process a Config.Sys hence is of no relevance) : easiest, DOSCode = FFFFh. Seems to be hardwired, HiMem is built-into IO.SYS and DOS is always loaded in the HMA (DOS=LOW has no effect).
Amusingly Microsoft seems to ignore this fact and includes a copy of HIMEM.SYS on their boot disquettes, which is just wasting space (unless you want to give HIMEM extra parameters, you may delete it).
- Case DOS 7.x : peek into DOSData, there is a table of 8 far pointers used by DOS to jump to the actual internal interrupt entries in its main code segment, whether in HMA or not.
Any one will do, they should all have the desired segment number - of particular interest may be the pointer to int 27 code, at DATA:0F8E, because that one points very near the Magic TEST Instruction, that could provide a double/triple checking if we wanted.
2 > How do you locate the instruction that has to be patched?
Search for the MTI and a few bytes of context. Actually the MTI alone appears to be unique in the CodeSeg, adding some context will render us quieter. And we could add more checks like the proximity to the int 27 entry per the above, or check vs. the offsets we found by manual examination of various versions of IO.SYS. The MTI should not wander too far away from its expected location, even allowing for internal revisions, QFEs and the like. Not all these checks will be needed I think.
3 > If you release the program (hopefully generally including the source), could you document the DOS data segment items that you found to be used by MS-DOS? I'm just interested.
I think I will provide the source code per request rather than make it downloadable anonymously. I'll try to make the comments readable and useful before that happens.
Cheers --- Ninho |
ecm
Düsseldorf, Germany, 12.12.2009, 22:40
@ Ninho
|
CM's questions, answered |
> - Case DOS 8 (checked the version of IO.SYS for floppies, since the
> regular one does not even process a Config.Sys hence is of no relevance) :
> easiest, DOSCode = FFFFh. Seems to be hardwired, HiMem is built-into IO.SYS
> and DOS is always loaded in the HMA (DOS=LOW has no effect).
I'd still rather use the other method here. If it works just as well, handling MS-DOS 8 separately only adds unnecessary code. Also, the XMM might find the HMA to be unavailable somehow and the kernel would then probably revert to another location. (Might be due to unknown A20 switch method, or only 1 MiB of physical memory. What are the odds of either with 386+ PCs?)
> Amusingly Microsoft seems to ignore this fact and includes a copy of
> HIMEM.SYS on their boot disquettes, which is just wasting space (unless
> you want to give HIMEM extra parameters, you may delete it).
Don't they load the internal driver unconditionally (before processing CONFIG.SYS), thus rendering the executable completely useless?
> - Case DOS 7.x : peek into DOSData, there is
Where? Or rather: How do you find that table? If I'd want to find it now, I'd look at the interrupt vector for one of the unaltered interrupts in my debugger. Your way might be able to find the table even with all these interrupts hooked.
> I think I will provide the source code per request rather than make it
> downloadable anonymously.
I'll just state it flat out: I do not agree with this; I don't see a reason to exclude the source generally but to make it available per request nonetheless. (Of course this still is better than not providing source at all, therefore I thank you. I just don't see why not to provide it directly.) --- l |
Ninho
13.12.2009, 00:10
@ ecm
|
CM's questions, answered |
>> - Case DOS 8 ...
>> DOSCode = FFFFh. Seems to be hardwired, HiMem is built-into IO.SYS
>> and DOS is always loaded in the HMA (DOS=LOW has no effect).
> I'd still rather use the other method here. If it works just as well,
> handling MS-DOS 8 separately only adds unnecessary code.
Read again, Mister. The DOS7 method won't work in DOS 8, and vice versa. DOS8 CS=FFFF is hardcoded, it's how they built it. MS-DOS 8 is intended as a launcher for Windows ME, not as a compatible all purpose DOS.
> Also, the
> XMM might find the HMA to be unavailable somehow and the kernel would then
> probably revert to another location.
No, no, no! It's hard coded my friend. The necessary mechanics to load DOS elsewhere have been removed (which also makes DOS8 marginally faster than its predecessor). Do like me, just look at the code (if like me you don't own ME, you can make a DOS 8 diskette from Win XP, or download one from many sites. Just remove the junk and study the code!)
>(Might be due to unknown A20 switch
> method, or only 1 MiB of physical memory.
DOS couldn't load. In the better case they'll output a cryptic message (you must reinstall Windows ME ???), or, as we know Microsoft, might simply crash. I don't know which, care to check ? Use an emulator and somehow break the HMA...
Not that you could find a PC using a totally exotic A20 control method these days.
And ME wasn't supposed to run on a 386. I believe it's "Pentium or better" (Win 95 : 386+, 98: 486DX IIRW).
>> Amusingly Microsoft seems to ignore this fact and includes a copy of
>> HIMEM.SYS on their boot disquettes, which is just wasting space (unless
>> you want to give HIMEM extra parameters, you may delete it).
> Don't they load the internal driver unconditionally (before processing
> CONFIG.SYS), thus rendering the executable completely useless?
My bet is they load the standalone HIMEM, or another XMS driver, as specified in Config.sys. The reason there IS a himem.sys must be precisely to allow specifying special parameters. In the majority of cases nowadays, the built-in HIMEM with default params and A20 method autodetection should work.
Not that I am a regular user of Win-ME (who is ? )
>> - Case DOS 7.x : peek into DOSData, there is
> Where? Or rather: How do you find that table? If I'd want to find it now,
> I'd look at the interrupt vector for one of the unaltered interrupts in my
> debugger. Your way might be able to find the table even with all these
> interrupts hooked.
Yes of course it is and is the reason I choose this way. The interrupt table is the worst possible option, unless you're prepared for hardcore virus-like following and possibly even tracing of the interrupt chains !
>> I think I will provide the source code per request rather than make it
>> downloadable anonymously.
> I'll just state it flat out: I do not agree with this; I don't see a
> reason to exclude the source generally but to make it available per
> request nonetheless. (Of course this still is better than not providing
> source at all, therefore I thank you. I just don't see why not to provide
> it directly.)
I like to get an idea of who requests the code, how many samples, their expectations, and possibly get some feedback. Do you think an informal email request is too much to ask of them ? If it were, rather cast margaritas ante porcos.
It's not like I'm concealing trade secrets, on the contrary, I am set up to explain clearly the hows and whys, namely in answers to this forum, in a manner which I think for most people makes more sense than an assembly listing.
I don't expect more than a handful persons to be really interested in the ASM code (you being an exception!); I'll change my mind in case I'm overwhelmed by a flow of requests
--
Ninho --- Ninho |
ecm
Düsseldorf, Germany, 13.12.2009, 00:51
@ Ninho
|
CM's questions, answered |
> Read again, Mister. The DOS7 method won't work in DOS 8, and vice versa.
> DOS8 CS=FFFF is hardcoded, it's how they built it.
Okay.
> MS-DOS 8 is intended as
> a launcher for Windows ME, not as a compatible all purpose DOS.
It still contains lots of stuff not required just for launching Windows.
> (which also makes DOS8 marginally faster than its predecessor).
You probably won't notice on 586+ machines.
> if like me you don't own ME,
I do own it.
> >(Might be due to unknown A20 switch
> > method, or only 1 MiB of physical memory.
>
> DOS couldn't load. In the better case they'll output a cryptic message
> (you must reinstall Windows ME ???), or, as we know Microsoft, might
> simply crash. I don't know which, care to check ? Use an emulator and
> somehow break the HMA...
I don't care, really. They probably crash, just as they don't check for a 386+ CPU.
> And ME wasn't supposed to run on a 386. I believe it's "Pentium or better"
> (Win 95 : 386+, 98: 486DX IIRW).
Windows 4 certainly won't run well on a 386 PC but MS-DOS 7/8 alone should run.
> Not that I am a regular user of Win-ME (who is ? )
I has been using it some years. It's not as bad as they say; especially the native USB support was a lot better than 98 SE's. (I.e. it was actually usable.)
> >> - Case DOS 7.x : peek into DOSData, there is
>
> > Where? Or rather: How do you find that table? If I'd want to find it
> now,
> > I'd look at the interrupt vector for one of the unaltered interrupts in
> my
> > debugger. Your way might be able to find the table even with all these
> > interrupts hooked.
>
> Yes of course it is and is the reason I choose this way.
Umm, I asked where/how you find that table in the DOS data segment.
> I like to get an idea of who requests the code, how many samples, their
> expectations, and possibly get some feedback.
I don't think anyone will get in contact with you only because he "has to" ask you for the source. Rather I find it inconvenient to request it, because it does take more actual effort by me and I'll have to wait until you react to it.
> Do you think an informal
> email request is too much to ask of them ?
No, as I stated previously.
> It's not like I'm concealing trade secrets, on the contrary, I am set up
> to explain clearly the hows and whys, namely in answers to this forum, in
> a manner which I think for most people makes more sense than an assembly
> listing.
These people could go on and read your answers here instead of reading the provided source. I don't see how you, providing the source as download, would prevent them from doing so or you from writing these answers. |
Ninho
13.12.2009, 10:32 (edited by Ninho, 13.12.2009, 11:16)
@ ecm
|
CM's questions, answered |
>> Not that I am a regular user of Win-ME (who is ? )
> I has been using it some years. It's not as bad as they say; especially
> the native USB support was a lot better than 98 SE's. (I.e. it was
> actually usable.)
I didn't say WinME was all rubbish. What I did say is DOS 8, as can be ripped from a Windows ME, is not the best choice for an all-purpose MS-DOS; DOS 7.10 is more general.
>>> Where? Or rather: How do you find that table?
> Umm, I asked where/how you find that table in the DOS data segment...
Similar to how Ralf, Geoff, I assume, and others do : by peeking at the codes, including initialisation stuff, making deductions and experimenting as needed.
As far as I know, "reversing" code (Fravia's word; did you know he passed away, recently?) for personal learning is still *not* considered criminal in this land of the crazy; it shoudln't be anyway.
...
>> It's not like I'm concealing trade secrets, on the contrary, I am set up
>> to explain clearly the hows and whys
Excuse me if I seem to fail to discern clearly what you are asking for.
If you're trying to suggest I should make a web page of organised notes about the (small part) of MS-DOS 7+ internals that I have explored, it is a good idea. I'll consider doing so, but please understand that programming is not my main interest in life, there are other subjects I would make pages about if I were to start a personal site. Certainly someone should take up the task of updating Ralf Brown's "int list" from where he left off, including the DOS 7+ reference data.
> These people could go on and read your answers here instead of reading the
> provided source. I don't see how you, providing the source as download,
> would prevent them from doing so or you from writing these answers.
Everybody's welcome to read my prose, not that it's so interesting --- Ninho |
geoffchappell
14.12.2009, 10:41
@ Ninho
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
> - I pick an unused bit in the SAME byte for a new flag which HACKWRAP, or
> dare I say FIXDOS ;=) will set during of Config.sys.
There's a luxury that comes with knowing that there will be no more DOS versions from Microsoft. It would not have occurred to me to define a new bit: I'm still thinking as I was back in 1996!
> An other instance of HACKWRAP, or a companion program will later unset
> the flag, restoring the usual DOS working (an oxymoron?)
To me, this is fundamentally unsound. What if your other instance doesn't load? You disturb the system without ensuring that you will un-disturb it.
> So, what FIXDOS/HACKWRAP does is we'll FLIP one bit in that instruction,
> in memory, that will change it to TESTing for both OUR new bit and THEIRS
> and the following JNZ will take the proper action in all cases, skipping
> over the bookkeeping whenever it is unwanted !
So, you will find the TEST instruction and patch it to recognise your new bit, and then also set your new bit before WRAPPER.SYS and clear it after. Why define a new bit to set and clear? Since you still must patch the TEST instruction, why not just patch the JNZ that follows it (and patch it back later)? |
geoffchappell
14.12.2009, 10:42
@ Ninho
|
CM's questions, answered |
> 1 > How do you find the DOS code segment?
>
> There are more than one roads.
You perhaps do not have to go as far as finding which segment DOS itself uses for addressing its code. Since you have no interest in the address of the TEST instruction, you just have to find it with sufficient assurance that you have the right one. |
Ninho
14.12.2009, 11:49 (edited by Ninho, 14.12.2009, 12:11)
@ geoffchappell
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
>> - I pick an unused bit in the SAME byte for a new flag which HACKWRAP, or
>> dare I say FIXDOS ;=) will set during of Config.sys.
> There's a luxury that comes with knowing that there will be no more DOS
> versions from Microsoft. It would not have occurred to me to define a new
> bit: I'm still thinking as I was back in 1996!
Indeed it is a relief to know MS will never stamp on my bit.
On the flip side, in your case, you have the luxury of regaining control automatically once an embedded TSR have been terminated by DOS.
Fixwrap by being standalone cannot be called back in that manner, at least there is no easy solution for it to be.
>> An other instance of HACKWRAP, or a companion program will later unset
>> the flag, restoring the usual DOS working (an oxymoron?)
> To me, this is fundamentally unsound. What if your other instance doesn't
> load? You disturb the system without ensuring that you will un-disturb it.
Agreed just in principle. I could reply that won't happen if users RTFM :=)
Also it won't be a problem if they stay in DOS, only if they eventually launch Windows and only if they carelessly launched more TSRs without UNfixwrapping. Let'm RTFM !
I haven't given much thought yet to how far I want to make the "companion program" comprehensive versus simple (it would not be a separate binary, rather a combined .exe or .com type driver/executable). I'm finishing the first FIXWRAP first, so we have something to play with.
But yes, again, ideally we should ensure the "fix" is rendered inactive as soon as Sysinit finishes loading the config.sys drivers.
If I can devise a /simple/ scheme whereby the first FIXWRAP device stayed in memory to be callback'ed after all drivers have been initialised, I will consider employing that to avoid the users pain. You may have ideas!
While considering any method I will have to balance it with the ease and comfort that having none of FIXWRAP stay in memory provides !
Also I have to put some limits to the amount of self-inflinged work, perfection, alas! is not a thing of this world...
>> So, what FIXDOS/HACKWRAP does is we'll FLIP one bit in that instruction,
>> in memory, that will change it to TESTing for both OUR new bit and THEIRS
>> and the following JNZ will take the proper action in all cases, skipping
>> over the bookkeeping whenever it is unwanted !
> So, you will find the TEST instruction and patch it to recognise your new
> bit, and then also set your new bit before WRAPPER.SYS and clear it after.
> Why define a new bit to set and clear? Since you still must patch the TEST
> instruction, why not just patch the JNZ that follows it (and patch it back
> later)?
Mainly because I don't want to take the risk of breaking MS's case logic, nor even want or need to /know/ what the precise purpose is of those MS's bits.
Symbolically this is the patched test :
Magic_test: TEST Win386flags, MS_mask OR Ninho_bit
JNZ skip_unwanted ; jmp if any mask bit(s) is (are) set
In your proposition, i.e. without Ninho_bit, how exactly do you propose to change the TEST and JNZ ?
MS_mask is = 03 ( 01 in Win95 original "gold" say you, I haven't checked. A priori, the difference could be either an added feature of service packs, or a silent bug correction.) --- Ninho |
Ninho
14.12.2009, 12:19
@ geoffchappell
|
CM's questions, answered |
Hi, Geoff!
> You perhaps do not have to go as far as finding which segment DOS itself
> uses for addressing its code. Since you have no interest in the address of
> the TEST instruction, you just have to find it with sufficient assurance
> that you have the right one.
Yes I know but I /can/ find that segment easily enough and use it to do checks and locate the exact bounds of the actual code, per MCB and HmaContrlBlock. I prefer exact science, where available, to guesswork and black magic --- Ninho |
Ninho
14.12.2009, 20:37 (edited by Ninho, 14.12.2009, 22:48)
@ Ninho
|
the DOS code segment hunt, results/questions |
Back to tuning the algorithms after 2 days absorbed in (mostly) unrelated activities.
Spent several hours asserting and validating methods for reliably finding the DOS kernel's CS. The hunt was made a tad more difficult (hence exciting ) for I had in the case of DOS 7 to test all the combinations of DOS=HIGH/LOW, XMS loaded/not loaded...
Well , here come the results, in increasing order of satisfaction. Comments welcome :
1: the method I suggested earlier, viz eight far pointers @ DOSDATA:F7A ?
Nope, bad pick! The segment part of these pointers is correct ONLY if an XMS manager is loaded. Otherwise they are unused (bypassed) and DOS doesn't care to update the segment thereof, fair enough. The offsets are correct still so I may want to use the internal int27 one in checking the "magic test" instruction.
2: DOSDATA:90h. There are 15 far pointers who seem to point to DOSCODE always. I could use that, the infortune is I cannot find reference data about them. They don't seem to appear in Ralf's list. Geoff probably knows better, are you listening Geoff ?
3: WRING! see update below : DOS CS is kept near the start of IO.SYS data area @ 0070:0003. This location is apparently properly updated by DOS each time it moves its code during initialisation. It works also in DOS 8 (CS=FFFF)
[update] Is was too good to be true. I had yet to check DOS 7.0/Win 95 A... Ooops! Method 3 fails there...
OK, that leaves us with method 2. I have not seen a configuration of 95/95B/98SE where the fifteen FAR pointers starting @offset (90h) in DOS data segment did not point to the DOS CODE. Please speak up, whoever finds otherwise!
More suggestions ?
That's all folks ! --- Ninho |
ecm
Düsseldorf, Germany, 14.12.2009, 23:30
@ Ninho
|
the DOS code segment hunt, results/questions |
> 2: DOSDATA:90h. There are 15 far pointers who seem to point to
> DOSCODE always. I could use that, the infortune is I cannot find reference
> data about them. They don't seem to appear in Ralf's list. Geoff probably
> knows better, are you listening Geoff ?
Look for SHARE.EXE hooks; they're listed in the Int21.52 (DOS data) description. These hooks are either addressed with fixed offsets or by finding the first SFT container (segment must be the DOS data segment). The latter's offset is 0CCh, and just in front of it are the SHARE.EXE hooks.
Installing SHARE.EXE is legitimate under MS-DOS 7.00 and might work with a specially written FAT32 SHARE.EXE under MS-DOS 7.10+. (Microsoft simply omitted SHARE.EXE from MS-DOS 7.10 and never provided a FAT32 version.) Therefore, all of these pointers could be hooked by SHARE.EXE pointing to its segment instead of the DOS code segment.
> 3: WRING! see update below : DOS CS is kept near the start of IO.SYS
> data area @ 0070:0003. This location is apparently properly updated by DOS
> each time it moves its code during initialisation. It works also in DOS 8
> (CS=FFFF)
>
> [update] Is was too good to be true. I had yet to check DOS 7.0/Win 95
> A... Ooops! Method 3 fails there...
>
> OK, that leaves us with method 2. I have not seen a configuration of
> 95/95B/98SE where the fifteen FAR pointers starting @offset (90h) in DOS
> data segment did not point to the DOS CODE. Please speak up, whoever finds
> otherwise!
I'd say you should try working with method 3; MS-DOS 7.00 probably stores the code segment somewhere around there as did earlier and later versions. Method 2 might not be reliable especially with MS-DOS 7.00 due to SHARE.EXE being provided by Microsoft there. --- l |
Ninho
15.12.2009, 00:59 (edited by Ninho, 15.12.2009, 01:20)
@ ecm
|
the DOS code segment hunt, results/questions |
>> 2: DOSDATA:90h. There are 15 far pointers who seem to point to
>> DOSCODE always. I could use that, the infortune is I cannot find reference
>> data about them. They don't seem to appear in Ralf's list.
> Look for SHARE.EXE hooks; they're listed in the Int21.52 (DOS data)
> description. These hooks are either addressed with fixed offsets or by
> finding the first SFT container (segment must be the DOS data segment).
> The latter's offset is 0CCh, and just in front of it are the SHARE.EXE
> hooks.
Ah, right you are ! I was working by my partial compilation, hand written on paper after Ralf's tables, unfortunately at the position of these pointers I had retained only "DWORD pointer to FAR routine for ???", forgetting to note the relation to SHARE.EXE.
> Installing SHARE.EXE is legitimate under MS-DOS 7.00 and might work with a
> specially written FAT32 SHARE.EXE under MS-DOS 7.10+. (Microsoft simply
> omitted SHARE.EXE from MS-DOS 7.10 and never provided a FAT32 version.)
> Therefore, all of these pointers could be hooked by SHARE.EXE pointing to
> its segment instead of the DOS code segment.
Thank you Christian; I'll load SHARE and see the look of the routines therein, it might be feasible to trace back from there to the original ones in the kernel.
> I'd say you should try working with method 3; MS-DOS 7.00 probably stores
> the code segment somewhere around there as did earlier and later versions.
Method 3 was taking DOS CS from Word [70:3]. Unfortunately in MSDOS 7.0 it has the DOS DATA segment instead. Doesn't work out.
> Method 2 might not be reliable especially with MS-DOS 7.00 due to SHARE.EXE
> being provided by Microsoft there.
IIRC from way back, SHARE was not installed by default in Win 95 "A" install,
it mifht even not have been present on the installation media (at that time, most often *floppies*). Rather it was part of supplemental files that people could download from Microsoft's or others' BBS (Internet? B.Gates hadn't heard of the internet yet...) Hence the number of users still running 95 "A", /and/ loading SHARE at that, must be quicly approaching zero ;=) --- Ninho |
Ninho
15.12.2009, 10:32 (edited by Ninho, 15.12.2009, 11:34)
@ ecm
|
Aha! Share was a *red herring* ! Hunt over !!! |
> Installing SHARE.EXE is legitimate under MS-DOS 7.00 and might work with a
> specially written FAT32 SHARE.EXE under MS-DOS 7.10+.
FIXWRAP is executed as a DEVICE= driver installation. The user may well INSTALL=SHARE.EXE if s/he likes, we couldn't care less !!!
So evident, we must have been blind.
>> OK, that leaves us with method 2.
> I'd say you should try working with method 3; MS-DOS 7.00 probably stores
> the code segment somewhere around there as did earlier and later versions.
> Method 2 might not be reliable especially with MS-DOS 7.00 due to SHARE.EXE
> being provided by Microsoft there.
See now, method 2 it is
What's more, there never was a method 3 Much to my confusion I must admit, the DOS CODE segment never was recorded at 70:3, but the DATA Seg. A strange case of hallucination (or just fatigue).
Great brain-storming session, CM ! --- Ninho |
geoffchappell
15.12.2009, 16:55
@ Ninho
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
> But yes, again, ideally we should ensure the "fix" is rendered inactive
> as soon as Sysinit finishes loading the config.sys drivers.
> If I can devise a /simple/ scheme whereby the first FIXWRAP device
> stayed in memory to be callback'ed after all drivers have been
> initialised, I will consider employing that to avoid the users pain.
> You may have ideas!
Not easily, no. If you have to stay in memory, you may as well just "fix" DOS by providing temporary memory for TSR information. We're talking of not even half a KB of memory that is wasted - and if you do want to free it, then at least you can, whenever you want.
Your way would require possibly more than half a KB for code that stays active while watching for this or that condition. I don't know that this is a gain.
I incline to think that if you go with your method, you may as well leave it to the user's responsibility to repeat the loading of your driver as the last DEVICE entry. It is just a workaround, after all. If the user is unhappy, let him rewrite WRAPPER.SYS.
> Magic_test: TEST Win386flags, MS_mask OR Ninho_bit
> JNZ skip_unwanted ; jmp if any mask bit(s) is (are) set
At any time that your bit is set, you make DOS take the jump, and at any time your bit is clear, you leave DOS to decide whether to take the jump.
Since you're going to make DOS take the jump, why not just change the jump? The bit is redundant. At any time that you would set your bit, just change the JNZ to a JMP SHORT, and at any time that you would clear your bit, just change the JMP SHORT back to a JNZ.
> In your proposition, i.e. without Ninho_bit, how exactly do you propose
> to change the TEST and JNZ ?
Leave the TEST alone. Change the 0x75 to 0xEB.
> Yes I know but I /can/ find that segment easily enough and use it to
> do checks and locate the exact bounds of the actual code, per MCB and
> HmaContrlBlock. I prefer exact science, where available, to guesswork
> and black magic
I think you'll end up with quite a lot of the latter. What the "exact science" points to, over and over, is that the DOS code segment is not meant to be found - well, not by anyone but DOS itself.
Besides, what good is it to you to know what segment DOS uses for accessing its code? It's just an addressing base. It doesn't tell you where the DOS code starts, let alone where it ends. You're going to be involved in some heuristics, come what may.
> DOS CS is kept near the start of IO.SYS data area @ 0070:0003.
It holds the DOS data segment, as far as I ever knew. It was always a handy thing to know when debugging. |
geoffchappell
15.12.2009, 16:56
@ ecm
|
the DOS code segment hunt, results/questions |
> Look for SHARE.EXE hooks; they're listed in the Int21.52 (DOS data)
> description.
That listing always puzzled me. I don't believe anyone ever had any evidence of any Microsoft code accessing the SHARE hooks relative to the address returned by int 21h function 52h. As you noted, SHARE uses hard-coded offsets for these pointers (005Ch or 0090h). It's one of those programs that know the layout of DOS data depends on the indicator at offset 04h.
I don't recall any location of the pointers via the first SFT container. Mind you, I don't seem to have any disassemblies of SHARE after DOS 4. I must have looked at it later, but not everything got preserved when I moved from one side of the world to the other. It's quaint now, but back in the late 80s and early 90s, I used to mark up these things with pencil and paper. It was the hard copy that was vital. Marking up the file - and never printing out - didn't take over until about 1992.
Curiously, for access to variables that obviously are in the SYSVARS structure, SHARE sometimes accesses them as members but sometimes uses hard-coded offsets. That may be unintended, of course: the names of the variables and the members are perhaps the same, so that the difference is just the accidental omission of a "[bx].".
> MS-DOS 7.00 probably stores the code segment somewhere around there as
> did earlier and later versions.
I'm pretty sure it doesn't and never has. Once the code's at its final position, the segment only has to persist in far pointers that connect data to code. For instance, if DOS actually has ended up in the HMA, then there's a pointer so that int 21h can get from the stub in low memory to the code in high memory, but that pointer otherwise won't be meaningful. Of course, in the "otherwise" case, you can find the code segment by other ways.
If you really wanted to, you could reliably find the code segment experimentally. DOS calls various interrupts, most notably int 2Fh, directly from its code wherever its code may be. So, hook int 2Fh and call a DOS function that you know will call a particular case of int 2Fh. When your hook sees this case, it can look up the return address and save it for you. When the DOS function returns, you can unhook. The first one that comes to mind is that int 21h function 0Dh always finishes by calling int 2Fh function 1120h - but there's surely a better one than that. |
Ninho
15.12.2009, 19:08
@ geoffchappell
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
> I incline to think that if you go with your method, you may as well leave
> it to the user's responsibility to repeat the loading of your driver as
> the last DEVICE entry. It is just a workaround, after all. If the user is
> unhappy, let him rewrite WRAPPER.SYS.
Couldn't agree more. After all, a user savvy enough to play with WRAPPER.SYS must be capable of RTFMing.
>> Magic_test: TEST Win386flags, MS_mask OR Ninho_bit
>> JNZ skip_unwanted ; jmp if any mask bit(s) is (are) set
> At any time that your bit is set, you make DOS take the jump, and at any
> time your bit is clear, you leave DOS to decide whether to take the jump.
>
> Since you're going to make DOS take the jump, why not just change the
> jump? The bit is redundant. At any time that you would set your bit, just
> change the JNZ to a JMP SHORT, and at any time that you would clear your
> bit, just change the JMP SHORT back to a JNZ.
> Leave the TEST alone. Change the 0x75 to 0xEB.
Yeah, there's more than one way to skin this cat. I still see advantages to having a separate switching bit in the DOS data segment : undoing the fix is then as simple as switching this bit off, no need to replay the code chasing game. Also, I certainly wouldn't /modify system files/ on anonymous clients' disks, but you and me and all the members here, could easily patch the one bit of code in /our/ copies of IO.SYS, once and for all, and then the FIXWRAP becomes as simple as flipping one data bit without all the heuristic work nor magics, black or otherwise. Oh well...
>> and black magic
> I think you'll end up with quite a lot of the latter. What the "exact
> science" points to, over and over, is that the DOS code segment is not
> meant to be found - well, not by anyone but DOS itself.
>
> Besides, what good is it to you to know what segment DOS uses for
> accessing its code? It's just an addressing base. It doesn't tell you
> where the DOS code starts, let alone where it ends. You're going to be
> involved in some heuristics, come what may.
It's not not exact science perhaps, but not too far. I combine the exact CS value that DOS uses (from the yet unmodified SHARE hooks) with the offset of Int27_entry (found at DOSDATA:F8E), and I bet you the "magic test" is fourteen bytes ahead of that! However I do not have to rely on the distance being 14 bytes - in practice though the code from the MTI to int27entry was unchanged in all samples I have examined, from Windows 95 Gold to Windows ME.
(Apart from the magic byte itself being 01 in 95A and 03 later).
>> DOS CS is kept near the start of IO.SYS data area @ 0070:0003.
> It holds the DOS data segment, as far as I ever knew. It was always a
> handy thing to know when debugging.
Yeah sorry. I already noted in another message, it was just brain fart --- Ninho |
ecm
Düsseldorf, Germany, 15.12.2009, 21:13
@ Ninho
|
Aha! Share was a *red herring* ! Hunt over !!! |
> > Installing SHARE.EXE is legitimate under MS-DOS 7.00 and might work with
> a
> > specially written FAT32 SHARE.EXE under MS-DOS 7.10+.
>
> FIXWRAP is executed as a DEVICE= driver installation. The user may well
> INSTALL=SHARE.EXE if s/he likes, we couldn't care less !!!
>
> So evident, we must have been blind.
I don't like this. Say, a user loads FIXWRAP using DEVLOAD. This is of course not what users should do but they are able to. It's just no general solution to find the code segment, even restricting the OS to MS 7+.
I'd suggest you use the far jump at 0:C0 instead (the CP/M "CALL 5" compatibility entry). This either points directly to the DOS code segment or to one of the stubs in the DOS data segment. You can identify the stub and if it's one, you have to retrieve the address that it jumps to in its last instruction; this address points to the DOS code segment. To ensure that this will actually retrieve correct pointers, check that at 0:C0 there is indeed a far jump. You could probably decide where to search for the patch location using the CALL 5 handler instead of the Int27 handler as well. --- l |
ecm
Düsseldorf, Germany, 15.12.2009, 21:19
@ geoffchappell
|
the DOS code segment hunt, results/questions |
> > Look for SHARE.EXE hooks; they're listed in the Int21.52 (DOS data)
> > description.
>
> That listing always puzzled me. I don't believe anyone ever had any
> evidence of any Microsoft code accessing the SHARE hooks relative to the
> address returned by int 21h function 52h. As you noted, SHARE uses
> hard-coded offsets for these pointers (005Ch or 0090h). It's one of those
> programs that know the layout of DOS data depends on the indicator at
> offset 04h.
The Int21.52 description apparently has all the structures from the DOS data segment that didn't fit better at other locations. There are other structures there which aren't closely related to the main SYSVARS.
> I'm pretty sure it doesn't and never has. Once the code's at its final
> position, the segment only has to persist in far pointers that connect
> data to code. For instance, if DOS actually has ended up in the HMA, then
> there's a pointer so that int 21h can get from the stub in low memory to
> the code in high memory, but that pointer otherwise won't be meaningful.
> Of course, in the "otherwise" case, you can find the code segment by other
> ways.
You're correct; in case the code isn't moved to the HMA the interrupt vectors just point into DOS directly. --- l |
Ninho
15.12.2009, 22:32
@ ecm
|
Aha! Share was a *red herring* ! Hunt over !!! |
> I don't like this. Say, a user loads FIXWRAP using DEVLOAD. This is of
> course not what users should do but they are able to. It's just no general
> solution to find the code segment, even restricting the OS to MS 7+.
> Say, a user loads FIXWRAP using DEVLOAD. This is of
> course not what users should do but they are able to.
Your user is a vicious type, I assume s/he also loaded SHARE.EXE before trying to DEVLOAD FIXWRAP.SYS ? Let'm get what they deserve !
> It's just no general
> solution to find the code segment, even restricting the OS to MS 7+.
I find it good enough, until offered a better one, so let's read on :
> I'd suggest you use the far jump at 0:C0 instead (the CP/M "CALL 5"
> compatibility entry).
Oh! CP/M to the rescue! No, I don't think so
> This either points directly to the DOS code segment
> or to one of the stubs in the DOS data segment. You can identify the stub
> and if it's one, you have to retrieve the address that it jumps to in its
> last instruction; this address points to the DOS code segment.
Those stubs are NOT used and the segment therein is bogus whenever DOS=LOW and no XMS is loaded. Excuse me, I understand you are proud of your gimmick but so am I with mine own. Your method arrives at the same point as mine through more detours. And what if the motherf^cker of a user you have in mind (the one who devloads FIXWRAP) also messes with int 30 ? This is not serious !
To appease your fears, FIXWRAP could check whether it is being initiated by DOS or whether by a DEVLoader, it is not very difficult.
> the patch location using the CALL 5 handler instead of the Int27 handler
> as well.
I chose int 27 because it leads us almost right to the point of interest !
Cheers --- Ninho |
Ninho
15.12.2009, 22:38
@ ecm
|
the DOS code segment hunt, results/questions |
> You're correct; in case the code isn't moved to the HMA the interrupt
> vectors just point into DOS directly.
*Not* sure this is completely correct. I think the interrupt will pass through the hooks in the data seg whenever HIMEM.SYS is loaded even if DOS=LOW. BICBW.
Closing the shop for awhile... --- Ninho |
ecm
Düsseldorf, Germany, 15.12.2009, 23:05
@ Ninho
|
Aha! Share was a *red herring* ! Hunt over !!! |
> > This either points directly to the DOS code segment
> > or to one of the stubs in the DOS data segment. You can identify the
> stub
> > and if it's one, you have to retrieve the address that it jumps to in
> its
> > last instruction; this address points to the DOS code segment.
>
> Those stubs are NOT used and the segment therein is bogus whenever DOS=LOW
> and no XMS is loaded.
Yes. In this case, the jump at 0:C0 doesn't point to the stub. It points directly into the code segment, as I said above.
> And what if the motherf^cker of a user you have in
> mind (the one who devloads FIXWRAP) also messes with int 30 ?
No one messes with Int30.
> I chose int 27 because it leads us almost right to the point of interest
Yes it does. But if you were to use the CALL 5 entry pointer anyway it would be more convenient to use it for this purpose as well instead of tracking down the (used or unused) Int27 stub in the DOS data segment. --- l |
ecm
Düsseldorf, Germany, 15.12.2009, 23:06
@ Ninho
|
the DOS code segment hunt, results/questions |
> > You're correct; in case the code isn't moved to the HMA the interrupt
> > vectors just point into DOS directly.
>
> *Not* sure this is completely correct. I think the interrupt will pass
> through the hooks in the data seg whenever HIMEM.SYS is loaded even if
> DOS=LOW. BICBW.
I just set DOS=LOW in my CONFIG.SYS for MS-DOS 7.10, and it didn't go through the stubs even though an XMM is loaded. --- l |
Ninho
16.12.2009, 09:22
@ ecm
|
the DOS code segment hunt, results/questions |
> > > You're correct; in case the code isn't moved to the HMA the interrupt
> > > vectors just point into DOS directly.
> >
> > *Not* sure this is completely correct. I think the interrupt will pass
> > through the hooks in the data seg whenever HIMEM.SYS is loaded even if
> > DOS=LOW. BICBW.
>
> I just set DOS=LOW in my CONFIG.SYS for MS-DOS 7.10, and it didn't go
> through the stubs even though an XMM is loaded.
Correct ! The odd case I had in mind was the converse : DOS=HIGH but NO XMSMGR.
Then DOS sets up and uses the hooks in DOSDATA to jump to DOSCODe even though the latter is not in HMA.
Whatever... As far as finding DOS CS, I am sticking with my method - and could later adopt Geoff's int 2F callback as a complement or replacement if needed. The devious use of "devload" to try and break fixwrap doesn't bother me, but I could detect such attempts by looking up the (grand)parent PSP (been there done that).
I shall now go on with the main coding task. Also real life occupations, with XMas approaching ! Expect less messages from me for awhile, I'll still peek at the board.
Cheers --- Ninho |
Ninho
16.12.2009, 19:51 (edited by Ninho, 17.12.2009, 16:43)
@ Ninho
|
the algorithm, sketched for review. Nitpicks ? |
After the great collective brain storming, here's for review a rough sketch of the algorithm I settled for finding the Magic Test Instruction & installing the fix. I think it's not far from the ideal, viz produces the correct result using the least amount of effort.
Pre-assertions :
- the code is running as part of the driver's initialisation routine.
- Win95/DOS 7 (any version). The DOS8 case is merged somewhere along the path below, and is only simpler because so much is hardcoded.
Finding and fixing the Magic Test Instruction, step by step; being programmers, our first step has to be step zero, right ?
-0. Check SHARE not installed (should not really be needed since SHARE.EXE can't be installed before driver initialisations, but this step is to please CM and guard against his hypothetical mad hacker trying to DEVLOAD FIXWRAP after loading a version of SHARE.EXE) :
Use Int 2F/1000. -> AX=0 or 1, OK for us to continue; else bail out.
-1. Get CS:IP of int 27 in DOS Kernel :
CS from IOSYS share hooks (DATA:0092),
IP from MSDOS Data:0F90
IF this routine entry is NOT in the HMA, GOTO step 3 below.
-2. Else MS-DOS is "high" using the HMA, ergo XMS must be present :
-2a. check int 2F/4300 -> AL=80h. Else (incoherent! output dbg msg and bail out)
-2b. int 2F/43.10 -> get the far entry point to XMM functions,
-2c. Call with AH=5, the LOCAL Open HMA function. -> AX=0001 OK (else incoherence, dbg msg, undo work, bail out)
-3. Locate the Magic Test instruction :
We start by checking for the MTI straight at (int27_entry - 0Eh).
This is justified by my tests always finding the same layout of the code around this point in samples of MS-DOS 7.0, 7.1 (also 8). PLEASE everybody who can have a look, can we assert the MTI is always exactly fourteen bytes ahead of the int 27 entry in MSDOS code in all your versions, including national variations of Win 9x/ME ?
Of course we needn't rely on the offset of MTI with respect to Int27 being fixed. If the MTI was not found in its expected location, we may start searching for it (in the vicinity only??? Warn, for debugging purposes. TBD)
If NO magic instruction was found, error! mesg, undo work, bail out...
-4. TEST and SET Ninho's bit in the MTI. This establishes the fix proper (and could be applied permanently to the IO.SYS file, if desired). If the bit was set already, put a message (notice, rather than an error).
IFF we had opened the HMA in step 2c, now close it (locally!) using
XMS function 6.
-5. Finally, switch the fix ON, i.e. prevent DOS 21/31 from checking the TSRs, by setting Ninho's bit in DOSDATA offset F5B. Yell : Cocorico !!!!
(If the bit was found to be SET already, user may be loading FIXWRAP multiple times. No harm done, Warn only)
The rest is routine work : clean up, fill in exit values to caller, RETf to DOS Sysinit.
_______________________________________________________________________
Compared to the sweat of installation, the later undoing of the fix will be trivial and does not need much more than, switch Ninho's bit off at DATA:F5B
[Dec 17 : Typo corrected, thanks CM] --- Ninho |
Ninho
16.12.2009, 20:24
@ geoffchappell
|
the DOS code segment hunt, results/questions |
> If you really wanted to, you could reliably find the code segment
> experimentally. DOS calls various interrupts, most notably int 2Fh,
> directly from its code wherever its code may be. So, hook int 2Fh and call
> a DOS function that you know will call a particular case of int 2Fh. When
> your hook sees this case, it can look up the return address and save it
> for you. When the DOS function returns, you can unhook. The first one that
> comes to mind is that int 21h function 0Dh always finishes by calling int
> 2Fh function 1120h - but there's surely a better one than that.
Nice and easily applied trick, thank you very much! Didn't you tell you had forgotten you DOS basics
However the principle of least work (or simple=pretty) makes me stick to my current method (pick the DOS CS from the pristine share hooks). Of course I'll switch to using your method IFF someone find a convincing case where mine is in fault - when looking for the kernel CS during drivers init phase, be it clearly stated. I agree your method is the better one to use in the general case. --- Ninho |
ecm
Düsseldorf, Germany, 17.12.2009, 16:19
@ Ninho
|
the algorithm, sketched for review. Nitpicks ? |
> being programmers, our first step has to be step zero, right ?
If you get your interface right you can translate between user numbers and developer numbers at one point
> [...] this step is to please CM [...]
> Use Int 2F/1000. -> AX=0 or 1, OK for us to continue; else bail out.
A. The Int2F installation check doesn't return ax, it only returns al.
B. If it returns al = 01h then something strange is going on as well. Better to abort.
C. Int2F.1000 is not reliable. If you really want to please me you have to use a reliable installation check. (Hint: In front of the SDA, and seems NOT to be documented explicitly in RBIL.)
> CS from IOSYS share hooks (0070:0092),
You mean from DATA:0092.
> IF this routine entry is NOT in the HMA, GOTO step 3 below.
Make sure to add the offset*16 and segment for this check. An overflow (CY) means it's in the HMA. As you probably know MS-DOS 7 doesn't use segment FFFFh to address it's DOS code segment in the HMA. (FF39h here.)
> -4. TEST and SET Ninho's bit in the MTI. This establishes the fix proper
> (and could be applied permanently to the IO.SYS file, if desired). If the
> bit was set already, put a message (notice, rather than an error).
This notice might annoy those who patched their kernel file. Might just leave it out, or at least display it on the same line as the program name. --- l |
Ninho
17.12.2009, 16:35
@ geoffchappell
|
new HACKWRAP fix for MS-DOS7+, aka smashing the bug |
> Since you're going to make DOS take the jump, why not just change the
> jump? The bit is redundant.
The more I think of it the more I'm happy with the dual bit option. They play a different role than each other and work together nicely.
The MAGIC_Bit which we patch inside of the DOS kernel signals that the bug fix has been applied; Ninho's flag bit in DOS Data is what is used to SWITCH the fix on and off as instructed per DEVICE=HACKWRAP.SYS directives.
Now examine all the combinations of MAGIC and SWITCH and what they signify to us when we are launching "DEVICE=HACKWRAP ON ".
CASE 00: MAGIC_Bit and Ninho_SWITCH BOTH zero : the DOS is still unpatched (buggy!), this must be the first instance of HACKWRAP, so patch-in the fix and switch Fixwrap on (Set bits to 11)
CASE 10: MAGIC is ON but SWITCHed OFF : the bug fix was applied, but the command bit os off. Maybe there has been a succession of HACKWRAP=ON/OFF invoocations, to be expected if e.g. you have a complex CONFIG.SYS with [MENU] and INCLDE=... directives.
This case may also happen on the first invocation of FIXWRAP, if the IO.SYS file had the MAGIC permanently patched in.
Action : switch Fixwrap ON again. (->11)
CASE 11: Both bits ON : Fixwrap already active, leave as is =11). Warn, no error.
CASE 01: DOS unpatched yet but Ninho's SWITCH bit was ON : is an ERROR. Other software has "owned" Ninho's bit, YELL! and quit. Better not declare war on an unidentified enemy.
I think things are turning out quite nicely. We'll be taking off ASAP.... --- Ninho |
Ninho
17.12.2009, 17:14
@ ecm
|
the algorithm, sketched for review. Nitpicks ? |
>> [...] this step is to please CM [...]
>> Use Int 2F/1000. -> AX=0 or 1, OK for us to continue; else bail out.
> A. The Int2F installation check doesn't return ax, it only returns al.
My bad. Be sure I check every detail when actually coding, the above sketch is just that... a rough sketch done to give you all something to chew (or bite) at
> B. If it returns al = 01h then something strange is going on as well.
> Better to abort.
Disagree. 01 signifies DOS cannot accept SHARE installation at this moment. In no way does it prevent us from setting up FIXWRAP. To us 01 just means SHARE is not installed. Nor do I expect it to ever be installed, again, we're a driver initialising itself. Share is a regular program. At the very soonest your mad tester would load share using WRAPPER (not sure it will work, just hypothesing), and as you know that must come after FIXWRAP !
> C. Int2F.1000 is not reliable. If you really want to please me you
> have to use a reliable installation check.
Postponed.
>> CS from IOSYS share hooks (0070:0092),
> You mean from DATA:0092.
Of course. Good catch, I've edited the posted sketch.
>> IF this routine entry is NOT in the HMA, GOTO step 3 below.
> Make sure to add the offset*16 and segment for this check. An overflow
> (CY) means it's in the HMA.
This is exactly how it is coded, Christian
>As you probably know MS-DOS 7 doesn't use
> segment FFFFh to address it's DOS code segment in the HMA. (FF39h here.)
The exact CS it uses was fetched and found in step 1.
>> -4. TEST and SET Ninho's bit in the MTI. This establishes the fix proper
>> (and could be applied permanently to the IO.SYS file, if desired). If the
> > bit was set already, put a message (notice, rather than an error).
> This notice might annoy those who patched their kernel file. Might just
> leave it out, or at least display it on the same line as the program name.
How's that annoying exactly ? Are you annoyed at every line of scrolling boot-up time messages?
Assuming they are not hidden behind the Windows logo screen, that is.
What's annoying in my book is if a program doesn't give a clue of what it's doing and what maybe going wrong.
Besides, the /sketch/ is that of the test version which we will have to try and make misbehave in all possible manners, so better it details what it's thinking it's doing. The final will have less messages, and may sport a /Quiet switch even.
Thanks for the nits... --- Ninho |
ecm
Düsseldorf, Germany, 17.12.2009, 20:32
@ Ninho
|
the algorithm, sketched for review. Nitpicks ? |
> Disagree. 01 signifies DOS cannot accept SHARE installation at this
> moment. In no way does it prevent us from setting up FIXWRAP. To us 01
> just means SHARE is not installed.
But who returns 01h there? "No one" you say? That's right! So if someone hooked Int2F only to return 01h then something is fishy.
> Nor do I expect it to ever be
> installed, again, we're a driver initialising itself. Share is a regular
> program. At the very soonest your mad tester would load share using
> WRAPPER (not sure it will work, just hypothesing), and as you know that
> must come after FIXWRAP !
As mentioned there's no official FAT32 SHARE.EXE. Replacements might allow (permanent) installation as driver.
> This is exactly how it is coded, Christian
Just have to make sure. Can't possibly let someone be wrong on our internet
> How's that annoying exactly ? Are you annoyed at every line of scrolling
> boot-up time messages?
Yes. One line per executable is acceptable.
> Assuming they are not hidden behind the Windows logo screen, that is.
I switch it off so that the messages can annoy me.
> What's annoying in my book is if a program doesn't give a clue of
> what it's doing and what maybe going wrong.
True. Therefore, error conditions might display longer reports. Some fact like that the code/data is already patched should fit into the single line.
> The final will have less messages, and may sport
> a /Quiet switch even.
Indeed. Such a switch should be necessary for drivers. I once patched away the startup message of the MORESYS driver because it annoyed me to no end. (Didn't have the source available right then.) --- l |
Ninho
17.12.2009, 21:05
@ ecm
|
the algorithm, sketched for review. Nitpicks ? |
> > Disagree. 01 signifies DOS cannot accept SHARE installation at this
> > moment. In no way does it prevent us from setting up FIXWRAP. To us 01
> > just means SHARE is not installed.
>
> But who returns 01h there? "No one" you say? That's right! So if someone
> hooked Int2F only to return 01h then something is fishy.
OK. Though this is mostly a distraction, I've just checked SHARE on Win 95 A. Both MS share.exe and a third party. They DO NOT touch the hooks at DOS:90h, which is the right thing for them to do BTW. The SHARE.EXE programs hook interrupts 20h, 21h, 2fh.
This means I do not need or want to check for the presence of Share, which was a bizarre thing for Fixwrap to do in the first place : let's get rid with step zero.
>
>> Nor do I expect it to ever be
>> installed, again, we're a driver initialising itself. Share is a
> regular
>> program. At the very soonest your mad tester would load share using
>> WRAPPER (not sure it will work, just hypothesing), and as you know that
>> must come after FIXWRAP !
> As mentioned there's no official FAT32 SHARE.EXE. Replacements might allow
> (permanent) installation as driver.
But wouldn't touch the internal pointers which are only for MS-DOS's consumption only, for processing the default interrupt calls related to share.
...
>> Assuming they are not hidden behind the Windows logo screen, that is.
> I switch it off so that the messages can annoy me.
Me too !
--
Ninho,
back to non-connected mode. --- Ninho |
ecm
Düsseldorf, Germany, 17.12.2009, 21:13
@ Ninho
|
the algorithm, sketched for review. Nitpicks ? |
> I've just checked SHARE on Win 95
> A. Both MS share.exe and a third party. They DO NOT touch the hooks at
> DOS:90h, which is the right thing for them to do BTW. The SHARE.EXE
> programs hook interrupts 20h, 21h, 2fh.
Hu? Well MS-DOS 6 SHARE.EXE did hook there and at Int2F only. And are you sure they hook Int20 but not Int27? Sounds strange.
> which was a bizarre thing for Fixwrap to do in the first place
Yes because you should use the pointer at 0:C1 instead of the SHARE.EXE hooks
> But wouldn't touch the internal pointers which are only for MS-DOS's
> consumption only, for processing the default interrupt calls related to
> share.
These pointers were meant to be hooked by SHARE.EXE, and I'm certain were only called by DOS, not changed. --- l |
Ninho
17.12.2009, 23:16 (edited by Ninho, 17.12.2009, 23:29)
@ ecm
|
the algorithm, sketched for review. Nitpicks ? |
> These pointers were meant to be hooked by SHARE.EXE, and I'm certain were
> only called by DOS, not changed.
The pointers were almost certainly updated when SHARE installed itself - on earlier versions of DOS. Not any more on DOS 7 it appears they aren't ever changed. So, where is the problem ? I've had enough of this ! As you know from the other subthread, Geoff suggested another sure fire way to find DOS CS, for use in the improbable case you come up with a REAL example defeating this simple method. I've programmed and tested Geoff's method, it's OK. The main reason I do not adopt his method immediately is the principle of simplicity, why call a disk function - why call any DOS function in fact - unnecessarily ?
As for the fake "int 30" call, it looks complicated and very flaky imho, but you haven't detailed what you had in mind. Please submit a detailed algorithm using the pointer at 0:C1h if you want to support your idea, otherwise we don't know where you are aiming. It's not enough to know that the call eventually leads to the DOS CS, is it? - you have to trace it through. Show me your algorithm starting from the contents of DWord[0:C1] to find DOS CS... I suggest you use a high level description for everybody to follow easily, else ASM or other programming language is OK. Be sure your algorithm works for every combination of DOS=HIGH/LOW with and without XMS. Pending that I won't hear any more about CPM compatibility calls and/or share hooks ;=) --- Ninho |
Ninho
18.12.2009, 13:04
@ ecm
|
digression : MSDOS 7 and SHARE.EXE revisited |
>> Both MS share.exe and a third party. They DO NOT touch the hooks at
>> DOS:90h, which is the right thing for them to do BTW. The SHARE.EXE
>> programs hook interrupts 20h, 21h, 2fh.
Apology: the above applied only to the 3rd party SHARE, from ROMDOS iirc.
> Hu? Well MS-DOS 6 SHARE.EXE did hook there and at Int2F only.
Correct, and it (Share.exe from DOS 6.2, version control hacked) does insert itself into the vectors starting at offset 90h inside of the DOS 7.0 data segment.
>> which was a bizarre thing for Fixwrap to do in the first place
I give up : I'll be using Geoff Chappell's method to find the DOS CS, even if it makes DOS flush disk buffers for no apparent reason
> Yes because you should use the pointer at 0:C1 instead of the SHARE.EXE
> hooks
I'm still waiting for you to show how you do this in practice --- Ninho |
ecm
Düsseldorf, Germany, 18.12.2009, 14:31
@ Ninho
|
digression : MSDOS 7 and SHARE.EXE revisited |
> even if it makes DOS flush disk buffers for no apparent reason
A. Set up fake drives.
B. Find another call which doesn't result in disk access.
C. Screw it, the buffers are flushed by each process termination anyway!
> > Yes because you should use the pointer at 0:C1 instead of the SHARE.EXE
> > hooks
>
> I'm still waiting for you to show how you do this in practice
Citing myself along the way:
> I'd suggest you use the far jump at 0:C0 instead
> (the CP/M "CALL 5" compatibility entry).
> To ensure that this will actually retrieve correct pointers,
> check that at 0:C0 there is indeed a far jump.
if byte[0:C0] != EAh goto error
ptr = dword[0:C1]
> This either points directly to the DOS code segment or to one
> of the stubs in the DOS data segment. You can identify the stub
> and if it's one, you have to retrieve the address that it jumps
> to in its last instruction; this address points to the DOS code
> segment.
if (word[ptr] == 9090h) || (word[ptr] == 03EBh)
(
ptr = (ptr & FFFF0000h) | word[ptr+8]
ptr = dword[ptr]
)
Done. The high word of the variable ptr is now the segment the DOS code is addressed with.
In the last step, you might want to verify that, additionally, a near call (E8h) as well as an indirect far jump with CS: override (2Eh, FFh, 2Eh) follow the double-NOP or short jump of the HMA stub. (Note that the stub is used by DOS in case the DOS code might be relocated to the HMA (DOS=HIGH set) but the short jump will only be patched to the NOP sequence if it actually got relocated. (DOS=HIGH set and XMM loaded.))
I don't know whether the stub looks the same in MS-DOS 8, you have to look into this if you want to adapt this method.
You might also verify that the actual code pointed to by ptr now is the CP/M entry; it starts with some sequence of pop, push and mov instructions. Look at your kernel for this. The sequence probably didn't change between most MS-DOS versions except the offsets into the code and data segment.
> You could probably decide where to search for the patch location
> using the CALL 5 handler instead of the Int27 handler as well.
I'll leave this to you. --- l |
Ninho
18.12.2009, 17:19
@ ecm
|
digression : MSDOS 7 and SHARE.EXE revisited |
Now there's an algorithm, that's better than hand waving
I'd like to applaud, I sincerely hoped you'd have something in your sleeve that I'd not perceived from your earlier hints; unfortunately your method is flawed, totally depending on the contents of interrupt vectors 30& 31h not being modified by a previous runner. DOS works perfectly without the CPM compatibility call in vector 30 of course - indeed I wonder why MS so carefully kept the mechanics of that completely unusable and obsolete interface! No program exists which relies on it, or if you could find one, it would be so old that it would probably face major problems on anything newer than MSDOS version 2
You tell me "somebody touching int 30 is not a serious threat" ? Probably not, but it's easier to imagine than some driver modifying the share hooks.
>> You could probably decide where to search for the patch location
>> using the CALL 5 handler instead of the Int27 handler as well.
No salvation here : DOS "exec" function just fills the 'call 5' location in the PSP from the contents of int vectors 30/31, whatever they may be. If you stuff FF FF FF FF FF at 0:C0, you'll find "FF FF FF FF" at the destination of the call 5 of all programs you'll launch thereafter. Try it if you don't believe me!
This, I think, closes the digression
Thanks, and regards... --- Ninho |
ecm
Düsseldorf, Germany, 18.12.2009, 18:19
@ Ninho
|
digression : MSDOS 7 and SHARE.EXE revisited |
> DOS works perfectly without the
> CPM compatibility call in vector 30 of course
That doesn't matter.
> No program exists which relies on it, or if you could find one,
> it would be so old that it would probably face major problems on anything
> newer than MSDOS version 2
The CP/M compat. interface only provides MS-DOS 1.x calls which are still supported by all later versions. However, that doesn't matter either.
> You tell me "somebody touching int 30 is not a serious threat" ? Probably
> not, but it's easier to imagine than some driver modifying the share
> hooks.
No one cares about Int30. You probably didn't even think of it!
Plus I don't understand while this should be easier to imagine than someone hooking the SHARE hooks. The SHARE hooks actually are useful to hook: either because you want to handle file sharing & locking, or maybe just because you want to monitor local file access this way. As you said about the CP/M interface, "no program exists which relies on it" so hooking it would be completely useless.
> >> You could probably decide where to search for the patch location
> >> using the CALL 5 handler instead of the Int27 handler as well.
>
> No salvation here : DOS "exec" function just fills the 'call 5' location
> in the PSP from the contents of int vectors 30/31, whatever they may be.
> If you stuff FF FF FF FF FF at 0:C0, you'll find "FF FF FF FF" at the
> destination of the call 5 of all programs you'll launch thereafter. Try it
> if you don't believe me!
A. How is this related to my quoted statement here?
B. I'm pretty sure EXEC fills the PSP field at 0006h with a pointer to 0:C0, not the pointer read from 0:C1. Therefore, even with a modified instruction/pointer at 0:C0 EXEC won't create different PSPs.
C. If you stuff FF FF FF FF at DATA:90 (or whichever SHARE hook you intend to use) your method won't work either. The difference being that SHARE actually changes your pointer legitimately (although not to FF FF FF FF). --- l |
Ninho
18.12.2009, 18:55 (edited by Ninho, 18.12.2009, 19:59)
@ ecm
|
digression : MSDOS 7 and SHARE.EXE revisited |
> C. If you stuff FF FF FF FF at DATA:90 (or whichever SHARE hook you intend
> to use) your method won't work either. The difference being that SHARE
> actually changes your pointer legitimately (although not to
> FF FF FF FF).
I won't argue any more which of your method or mine is stronger or weaker. We have seen neither was bullet proof, right ? So I bit it (the bullet), and am using the method outlined by Geoff instead.
! Forgot to answer that question in your earlier msg :
> I don't know whether the stub looks the same in MS-DOS 8, you have to look
> into this if you want to adapt this method.
I already explained, MSDOS 8 is a different beast, CS is fixed, there are NO stubs in DOS data and no need, either.
The digression/distraction is closed. I'm coding ATM, little time left before the usual XMas related occupations will assail us one more time...
Cheers, --- Ninho |
Ninho
20.12.2009, 02:44
@ Ninho
|
HACKWRAP.SYS news, testing |
It's taken much more time and efforts than anticipated, but at long last I have FIXWRAP (alpha 0.1) running and in test
I'll finalise and release the beta ASAP : stay tuned ! --- Ninho |
Ninho
23.12.2009, 00:07
@ Ninho
|
FIXWRAP.SYS 0.5 beta - released - please try it ! |
Just ready for the holidays ...
Please go see the new thread including download links. --- Ninho |
Ninho
30.12.2009, 10:50
@ Ninho
|
the DOS code segment hunt, results/questions |
>> hook int 2Fh and call
>> a DOS function that you know will call a particular case of int 2Fh.
>> ...One that
>> comes to mind is that int 21h function 0Dh always finishes by calling int
>> 2Fh function 1120h - but there's surely a better one than that.
A good one (that doesn't cause disk activity!) might be :
int 21/3801h will call int 2F/14xx provided the country code (in BX) is different than the current country code.
I'll be using that in a FIXWrap revision... --- Ninho |