Welcome to the new Woodmann RCE Messageboards Regroupment
Please be patient while the rest of the site is restored.

To all Members of the old RCE Forums:
In order to log in, it will be necessary to reset your forum login password ("I forgot my password") using the original email address you registered with. You will be sent an email with a link to reset your password for that member account.

The old vBulletin forum was converted to phpBB format, requiring the passwords to be reset. If this is a problem for some because of a forgotten email address, please feel free to re-register with a new username. We are happy to welcome old and new members back to the forums! Thanks.

All new accounts are manually activated before you can post. Any questions can be PM'ed to Kayaker.

Byte patching issue

RCE of Linux tools and programs.
sailor__eda
Junior Member
Posts: 24
Joined: Sun May 30, 2004 2:01 pm

Byte patching issue

Post by sailor__eda »

I'm facing a really strange problem that i wanted to share with everyone.
I'm trying to patch a series of bytes in a linux dynamic library. I'm patching a function call in two locations in identical ways.
Here is a code snippet

.text:084E165B 8B 0D 04 DE D7 09 mov ecx, var1
.text:084E1661 89 0C 24 mov [esp+68h+var_68], ecx
.text:084E1664 E8 E7 3A 00 00 call Func1 <= patching this
.text:084E1669 A3 08 DE D7 09 mov var2, eax
.text:084E166E 8B 1D 08 DE D7 09 mov ebx, var2
.text:084E1674 85 DB test ebx, ebx
.text:084E1676 74 3A jz short loc_84E16B2

Func1 returns the results in eax so I wanted to patch the call to be mov eax, 0h instead.

Hence I was patching E8 E7 3A 00 00 with B8 00 00 00 00.
I fire up my favourite hex editor, look for my byte sequence and make the necessary changes. In fact, I have to do this patch in 2 locations, fairly close to each other.

Here's when the fun starts. If disassemble my modified file after my changes, the 2nd patch location has mov eax, 0h exactly as I intended. The first patch location has mov eax, 383Eh!

I did this several times just to make sure I'm not screwing something up and everytime I have the same problem. In fact, after much trial and error, I realized that whatever immediate value I patched in, seemed to have a offset of 383Eh added to it. I fixed the problem by finding 0h-383Eh and using that value instead and that gave me mov eax, 0h.

So my question is what his happening here? Why is it that making the same change a few bytes below works correctly but not for the first location?
I was thinking it might have something to do with the relocation stuff in a dynamic library but that doesn't make sense for immediate values.

So what gives?

Sailor
User avatar
dELTA
Posts: 4209
Joined: Mon Oct 30, 2000 7:00 am
Location: Ring -1

Post by dELTA »

Just a wild guess here, but maybe something having to do with instruction prefixes? Sometimes they don't show up in the disassembly raw data bytes for instructions, but still modify the behavior of the instruction. Still a little strange behavior though, I agree...

Opcode gurus where are you, anyone? :)
"Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."
User avatar
Polaris
Posts: 223
Joined: Sun Jun 02, 2002 2:00 pm
Location: Invincible Cyclones Of FrostWinds
Contact:

Post by Polaris »

Hmmm... I cannot see anything wrong here... It should work correctly. In fact, from Intel's manual:

B8+ rd MOV r32,imm32 Move imm32 to r32

where +rd is "a register code, from 0 through 7, added to the hexadecimal byte given at the left of the plus sign to form a single opcode byte"... So everything is correct here, as register code for EAX is 0. :confused:
Stand In The Fog With So Cold A Heart... Watching The Death Of The Sun...
User avatar
dELTA
Posts: 4209
Joined: Mon Oct 30, 2000 7:00 am
Location: Ring -1

Post by dELTA »

Hmm, interesting, may it be a bug in IDA or some kind of mistake by yourself sailor__eda? This must be solved! :)

Please upload both the patched and unpatched version here (that is, if it is a non-commercial library, which would be my guess since it is on Linux, or am I wrong? Otherwise please PM me instead).
"Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."
sailor__eda
Junior Member
Posts: 24
Joined: Sun May 30, 2004 2:01 pm

Post by sailor__eda »

You initially thats what I thought as well, IDA is making an error in the disassembly; but then the program didn't work like it was supposed (i.e. if eax == 0). Only when I did the mov eax, -383Eh did it work.

Sailor_eda
naides
Posts: 1655
Joined: Sat Jan 12, 2002 12:00 pm
Location: Planet Earth

Post by naides »

Little experiment: Instead of patching B8 00 00 00 00 mov eax, 0

Patch it to:

xor eax,eax
nop, nop nop, nop

or some variation on the theme:
xor eax,eax
inc eax
dec eax
inc eax
dec eax


same result, different code and see what happens to the nops or inc/decs. . .

Perhaps somewhere else in the code the program is modifying the executable in memory and/or in disk?
sailor__eda
Junior Member
Posts: 24
Joined: Sun May 30, 2004 2:01 pm

Post by sailor__eda »

Hi Naides,

You know I did exactly what you mention in the first patch and it disassembled into something like
xor eax, XXXh - some number
push XXXYYh - something else
instead of xor eax, eax and nop's

I can send you the file if you're interested, pm me and let me know.

Thanks,

Sailor_eda
User avatar
dELTA
Posts: 4209
Joined: Mon Oct 30, 2000 7:00 am
Location: Ring -1

Post by dELTA »

I have not been able to look at the files you sent me yet in IDA or any other more advanced tool, but I quickly diffed them, and there were no patch mistakes as far as I can see.

Judging by the fact that this all happens both in IDA and "in reality" (i.e. the effect is confirmed when running the code) we can safely say that an IDA bug is out of the question anyway.

I'd say everything points to a relocation issue or similar effect, which would also be practically the only thing that would show up both in a static disassembly and during live debugging, and the behavior of a certain constant always being added/subtracted from the original bytes also supports this.

So, why would a "CALL rel32" instruction be "relocated"? I have no deeper detailed knowledge of relocation mechanisms, and even less so in Linux executables, but my guess is that the relative call is corrected/relocated for section alignment issues, and that the other similar call instruction that you mention, which is not modified by IDA and the loader in this way rather references a call within the same section (or similar feature in ELF executables), while this problematic one references a call in another section. Am I right?

If you would somehow be able to enumerate all relocation information in that file, I can bet you'd see a reference to this address.
"Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."
naides
Posts: 1655
Joined: Sat Jan 12, 2002 12:00 pm
Location: Planet Earth

Post by naides »

Sure Sailor. Please send me the files via PM.

One more venue to explore: The hex editor: If you patch the original file, save it, and immediately open it (Without running or disassembly)
with the same or another hex editor, are the patched bytes still
text:084E1664 B8 00 00 00 00
?????
I am wondering if the hex editor is not doing something estrange during the patching an Endian problem, I don't know. . .


Question 2: You mention two locations of patching: Do they point to the same function?

I would expect a relocation effect to modify both places, which call the same, relocated function.
User avatar
dELTA
Posts: 4209
Joined: Mon Oct 30, 2000 7:00 am
Location: Ring -1

Post by dELTA »

naides wrote:One more venue to explore: The hex editor: If you patch the original file, save it, and immediately open it (Without running or disassembly)
with the same or another hex editor, are the patched bytes still
text:084E1664 B8 00 00 00 00
?????
As mentioned above, I've confirmed the patch to be correct, yes.

naides wrote:I am wondering if the hex editor is not doing something estrange during the patching an Endian problem, I don't know. . .
Zero is 00 00 00 00 both in big-endian and small-endian you know. :devil: (just kidding, I'm understand that it could just as well theoretically have has messed up something else too, but as mentioned above, I've confirmed it to be correct anyway)

naides wrote:Question 2: You mention two locations of patching: Do they point to the same function?

I would expect a relocation effect to modify both places, which call the same, relocated function.
If both calls are themselves located in the same section (or otherwise alignable/relocatable/movable area), AND the calls are referencing the same function, then it is strange indeed, yes. Otherwise please see my relocation explanation/hypothesis above.
"Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."
naides
Posts: 1655
Joined: Sat Jan 12, 2002 12:00 pm
Location: Planet Earth

Post by naides »

dELTA wrote:As mentioned above, I've confirmed the patch to be correct, yes.
That makes two people that don't read the prince's posts carefully :o :o :loveu:
sailor__eda
Junior Member
Posts: 24
Joined: Sun May 30, 2004 2:01 pm

Post by sailor__eda »

I forgot to mention it, but in the files I've sent, only the problem call is patched, just FYI.

Thanks for looking at this, I was wondering if I was going crazy :)

Sailor_eda
evlncrn8
Posts: 456
Joined: Mon Apr 22, 2002 12:38 pm

Post by evlncrn8 »

u sure the proc call that you're patching (e8 xx xx xx xx -> b8 xx xx xx xx) takes NO parameters?
naides
Posts: 1655
Joined: Sat Jan 12, 2002 12:00 pm
Location: Planet Earth

Post by naides »

I took a look at your files.

If you look at this code in IDA view:

Code: Select all

.text:00A3781B                 mov     ecx, dword_140EE64
.text:00A37821                 mov     [esp+68h+var_68], ecx
.text:[color="Red"]00A37824                 call    Function1 [/color]<--  Problem
.text:00A37829                 mov     dword_140EE68, eax
.text:00A3782E                 mov     ebx, dword_140EE68
.text:00A37834                 test    ebx, ebx
.text:00A37836                 jz      short loc_A37872
[color="Red"].text:00A37838                 call    Function2[/color]
.text:00A3783D                 test    eax, eax
.text:00A3783F                 jnz     short loc_A37848
And see the same area in HEX view:

Code: Select all

.text:00A37820  01 89 0C 24 [color="Red"]E8 E7 3A 00  00[/color] A3 68 EE 40 01 8B 1D  ë$Ft:..ú[email protected]ï
.text:00A37830  68 EE 40 01 85 DB 74 3A  [color="Red"]E8 33 15 00 00[/color] 85 C0 75  [email protected]à¦t:F3§..à+u
.text:00A37840  07 31 D2 E9 B0 FE FF FF  8B 35 64 EE 40 01 89 34  1-T¦¦  ï[email protected]ë4
You'll see what is expected, E8 rel32 . But looking at the same code region with a hex editor, directly from disk:

00A37820 0189 0C24 E8FC FFFF FFA3 68EE 4001 8B1D [email protected]
00A37830 68EE 4001 85DB 743A E8FC FFFF FF85 C075 [email protected]:.......u
00A37840 0731 D2E9 B0FE FFFF 8B35 64EE 4001 8934 [email protected]



You see that the Call instructions in this region do not hold the relative address of the callee function code, but rather a place holder: FFFFFFFC (in little-endian). Dont be intimidated by the Fs, as a signed integer, it is just -4.




Actually all the calls around this code area that point to a named symbol follow a similar pattern: do not have an actual address but the very same place holder, instead of the relative function address.

Looking around for "ELF relocation" I ran into several articles:
http://www.linuxjournal.com/article/1059
http://www.securityfocus.com/infocus/1872

and others. . .


So it seems that IDA and the Linux Loader use the Global offset Table (GOT) and the Procedure Linkage Table (PLT) to resolve symbolic call addresses at load time/disassembly time. In this case it is blindly adding a number to the call "address" position, where the place holder is located.

Non symbolic calls, calls that don't point to a named symbol, either local or external, which are labeled by IDA something like:

call sub_A40336

are treated differently. They indeed follow the familiar format E8 rel32 when examined in both IDA Hex view and in direct disk Hex editor (I checked a few). This means that the call addresses for local calls are determined at compile time/link time which is the the usual for windows programs, instead of at load time.

So patching a call does not seem to be a good idea in ELF libraries, patching a jump or other strategy may work better.

[edit]
Little add-on: (If any one cares) I figured out why the space holder has FFFFFFFC,( -4) in it. At the time in which the loader fills in a relative distance to the space holder, an extra 4 bytes need to be subtracted to point to the beginning of the referred call in the formula:

Relative Offset = Current virtual Address + Symbol Virtual Address Pointer (From the TOC) -4

taking into consideration that the place holder is 4 bytes long. The -4 will in-line the correction.
User avatar
Polaris
Posts: 223
Joined: Sun Jun 02, 2002 2:00 pm
Location: Invincible Cyclones Of FrostWinds
Contact:

Post by Polaris »

Good find Naides, really nice explanation!
Stand In The Fog With So Cold A Heart... Watching The Death Of The Sun...
Locked