Bekijk Volledige Versie : Re[2]: Can't Preventing exploitation with rebasing
dullien@gmx.de
05/02/03, 21:36
Hey all,
bghn> DIGRESSION:
bghn> Dave Litchfield says you can call esp. I don't know Dave's
bghn> relationships with his registers but this doesn't work if I want
bghn> to get my eip on top of my shellcode. Always starts executing a
bghn> memory address for me. Maybe if I took esp out to dinner more
bghn> often then I could call it instead of having to jump on top of it.
bghn> Dave, any suggestions for the wine list?
bghn> END DIGRESSION.
Problem here is Intel ignoring it's own standards. The standard says
to first transfer control, then push the old EIP on the stack -- but
Intel CPU's since Pentium have done it the other way around, first
pushing EIP (and decreasing ESP), then setting EIP=ESP.
Cheers,
Thomas
Bugtraq User
05/02/03, 23:05
> Going back to exe image files and rebasing. Surely they can be rebased even
> without a .reloc section? All I need to do is edit the image base in the PE
> header then parse the assembly looking for absolute addresses such as
> function addresses, static variables etc and modify these addresses, too.
>
I'm sorry but I don't think this is feasible in real life. In a test
program it may seem possible, but try and apply it to a real PE executable
that actually does something and you will see that it is not. To even
begin to do what you suggest, you would need to:
1) Write a functional disassembler that understands instruction
boundaries and knows which instructions reference absolute addresses
(easy).
2) Understand parts of the code section that are not assembly
instructions, such as JMP tables used by switch statements, and similar
constructs (getting harder).
3) Understand and be able to predict unknown data types, or infer their
data type by where they may or may not be referenced within code (quite
difficult).
How do you know if \x44\x42\x41\x00 within a .data section is an absolute
address 0x414244 or if it is actually the string DBA\0?
For all that effort, you might as well develop a more worthwhile security
measure.
D.C. van Moolenbroek
05/02/03, 23:27
First, your "push 0x0042001C" instruction might also happen to push a
number, instead of an offset. How do you distinguish between offsets and
numbers?
Second, what about jumptables? How are you going to relocate code like this?
Sure, the offset to the jumptable is easy, but what about the jumptable
itself?
cmp ebx,256
jae <my_error_handler>
call [0x004200C0 + ebx*4]
It might even get much more tricky than that. As an example, suppose the
first line ended with "eax" instead of "256"... suppose the jumptable was
followed by a unicode-string... and then suppose that eax was filled with a
value just read from a file/socket/etc. Unrealistic? I don't think so. Try
to find the end of the jumptable in this case!
Remember, relocation has to be perfect in order to work. No mistakes are
allowed. And without .reloc data, your relocator will have to start
guessing, which *will* result in mistakes.
Regards,
David (yes another one)
"David Litchfield" wrote:
> Going back to exe image files and rebasing. Surely they can be rebased
even
> without a .reloc section? All I need to do is edit the image base in the
PE
> header then parse the assembly looking for absolute addresses such as
> function addresses, static variables etc and modify these addresses, too.
>
> For example assume an image base for an exe is 0x00400000 and the c code
> does
>
> printf("hello");
>
> This will generate something like
>
> push 0x0042001C // push pointer to hello
> call 0x00401060 // call printf
>
> If I then make the image base 0x00410000 and I also change
>
> push 0x0042001C
> call 0x00401060
>
> to become
>
> push 0x0043001C
> call 0x00411060
>
> then the exe should still run (as long as you get all the absolute
> addresses) and it has been rebased.
>
> ?
> David
>
--
class sig{static void main(String[]s){for// D.C. van Moolenbroek
(int _=0;19>_;System.out.print((char)(52^// (CS student, VU, NL)
"Y`KbddaZ}`P#KJ#caBG".charAt(_++)-9)));}}// -Java sigs look bad-
Michal Zalewski
05/02/03, 23:33
On Wed, 5 Feb 2003, David Litchfield wrote:
> For example assume an image base for an exe is 0x00400000 and the c code
> does printf("hello"); This will generate something like
>
> push 0x0042001C // push pointer to hello
> call 0x00401060 // call printf
>
> If I then make the image base 0x00410000 and I also change /.../ to
> become
>
> push 0x0043001C
> call 0x00411060
First of all, no, you do not change the call, on Intel, it's likely to be
a relative 32-bit call (E8 .. .. .. ..) within the code, and it's
relocable without any changes.
Also, what if I wanted to pass a value 4325404 (0x42001c) to this
function, and it is not a pointer, only looks this way? For example, some
FOO_ASYNC flag is defined as 0x400000, FOO_LOCK as 0x020000, and voila, OR
them and you have "a pointer".
In other cases, say, with register calls, it is getting even nastier,
because even if, one way or another, you managed to find out how every
single function is going to use its parameters (not likely), register
calls are still black magic.
--
------------------------- bash$ :(){ :|:&};: --
Michal Zalewski * [http://lcamtuf.coredump.cx]
Did you know that clones never use mirrors?
--------------------------- 2003-02-05 12:24 --
Crispin Cowan
06/02/03, 00:04
--------------enig93FA77790F10759446C6E054
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Alan DeKok wrote:
>Brian Hatch <bugtraq@ifokr.org> wrote:
>
>
>>People keep saying "but it won't stop everything", and that's true.
>>
>>
> Exactly. Even DES isn't "perfectly" secure, (i.e. unbreakable). It
>*obfuscates* the data, but does not *secure* it. The benefit of DES
>is that it has a provable level of obfuscation.
>
> This takes the security versus obscurity argument from the realm of
>personal opinion to one of quantitative statements. We should have a
>similar goal for this discussion.
>
With one other critical factor: Systems that can be *properly*
criticized for being "security through obscurity" have the property that
the "obscurity" factor is fixed at software release time, or earlier.
Thus the attacker need only crack the key once, and then own thousands
of copies.
Systematic diversity (as explored by me
<http://wirex.com/%7Ecrispin/crackerpatch.pdf>, Forrest et al, proposed
in Bugtraq yesterday by Huang, and here in this thread) is qualitatively
different in that the "key" (the degree of rebasing offset) can be
chosen at runtime. If it is chosen with sufficient entropy, then it is
as effective as a similar amount of entropy in your favorite crypto
system. More, because with crypto the attacker can grind on your
ciphertext off line, but with systematic diversity, the attacker has to
grind on your machine, which you tend to notice sooner or later :-)
Crispin
--
Crispin Cowan, Ph.D.
Chief Scientist, WireX http://wirex.com/~crispin/
Security Hardened Linux Distribution: http://immunix.org
Available for purchase: http://wirex.com/Products/Immunix/purchase.html
Just say ".Nyet"
--------------enig93FA77790F10759446C6E054
Content-Type: application/pgp-signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQE+QG185ZkfjX2CNDARAQ70AKDdeH2M3NBBolbjSW6jDp Baf84zUQCcD/oa
oGuEaKFWFn75Ej9H2WaQlts=
=JgfR
-----END PGP SIGNATURE-----
--------------enig93FA77790F10759446C6E054--
Alun Jones
06/02/03, 00:18
At 05:38 AM 2/4/2003, Charlie Root wrote:
>Rebasing might be usefull up to some point. But it contains a "mental"
>vulnerability. If one would apply this technique he would probably think
>he is safe and neglect updating his security. Oh, and one more thing...
>I'm not sure about this since I have little expirience in windows:
>security-patches don't relly on the same "genetic code" as exploits ? If
>one would rebase his entire system would he still be able to properly
>apply security patches ?
The worse problem, IMHO, is that rebasing executables and/or DLLs makes it
harder to report and fix any GPFs that do occur. If you report a GPF, it's
going to come out with an offset that doesn't represent the correct area of
code. Perhaps the Dr Watson log provides enough information for a savvy
developer to trace through and find where the _real_ address is in the base
code, but there's so little documentation on the information contained in a
Dr Watson log output, that most developers haven't the first clue of how to
find the function that's at fault, unless your addresses match theirs.
Alun.
~~~~
--
Texas Imperial Software | Try WFTPD, the Windows FTP Server. Find us at
1602 Harvest Moon Place | http://www.wftpd.com or email alun@texis.com
Cedar Park TX 78613-1419 | VISA/MC accepted. NT-based sites, be sure to
Fax/Voice +1(512)258-9858 | read details of WFTPD Pro for NT.
Todd Sabin
06/02/03, 00:55
David Litchfield <david@ngssoftware.com> writes:
> Going back to exe image files and rebasing. Surely they can be rebased even
> without a .reloc section? All I need to do is edit the image base in the PE
> header then parse the assembly looking for absolute addresses such as
> function addresses, static variables etc and modify these addresses, too.
This can't work in general. You need to have a list of what should be
relocated (the .reloc section), because otherwise you're just guessing
and may well guess wrong.
>
> For example assume an image base for an exe is 0x00400000 and the c code
> does
>
> printf("hello");
>
> This will generate something like
>
> push 0x0042001C // push pointer to hello
> call 0x00401060 // call printf
>
> If I then make the image base 0x00410000 and I also change
>
> push 0x0042001C
> call 0x00401060
>
> to become
>
> push 0x0043001C
> call 0x00411060
>
> then the exe should still run (as long as you get all the absolute
> addresses) and it has been rebased.
>
> ?
What would happen in this case?:
...
CheckSectionFlags (section,
IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_MEM_PURGEABLE);
...
It may generate something like
push 0x00420000 // push flags
push 0x00420148 // push section
call 0x00401290 // call CheckSectionFlags
If you try to rebase that without a .reloc section, as you describe,
you'll change the meaning of the program because you have no way to
tell that the 0x00420000 is a constant and not a relocatable reference
to something else. (The IMAGE... flags are from winnt.h and probably
meaningless the way I've used them above, but you get the idea...)
--
Todd Sabin <tsabin@optonline.net>
BindView RAZOR Team <tsabin@razor.bindview.com>
Deus, Attonbitus
06/02/03, 19:39
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
At 03:38 AM 2/4/2003, Charlie Root wrote:
>With all the respect... I think your ideea is a BAD one ! Why ? Well... It
>might be verry efective if one to... mhm... 100 persons would aply this
>technique. That's because hackers/worms wouldn't mind loosing a few
>servers if they got the rest of the world. But if this technique would
>became a standard then the worm-industry (if there is such a thing) would
>also evolve... making it brute-force the addreses. I admit that
>brute-forcing would slow down the worm/hacker/whatever... but this is no
>way of looking at the security. This is like protecting a house/store by
>putting 15 doors that all could be easily broken... Of course there is a
>chance that a thief trying to break in would get bored breaking door after
>door... but if he's really determined... Well... I guess I made my point.
A couple of things- one, David did not say "Stopping Worm Propagation with
Rebasing," he said "Preventing exploitation..." If only 100 people do it
where one has the capability to reloc, then right on. Let the other 74,900
people lick their wounds while I sip on a White Russian and giggle.
He never said it was a silver bullet, never said it would be a panacea,
never said it would apply to all applications. He offered the information
as an additional strategy one could use, where applicable, to mitigate
exploitation of your typical worm.
I completely disagree with the statement that worm writers would evolve to
brute-forcing addresses. Not only from a stability standpoint (if they
were lucky enough NOT to trash the service) but from a practical
standpoint... A worm's primary goal is to propagate to infect-able systems
before the jig is up. They will not go through the trouble of trying to
BF a jmp address when they might draw attention and prematurely alert the
target population to the attempt. They will go for the low hanging fruit
every time. Hell, that is why they jacked David's vector code in the first
place; they did not want to go through the trouble of doing it themselves.
Could Halvar do it? Sure- in a nanosecond. But I'm not building security
in depth measures against people like Halvar and David (there's really no
point in that.) I'm building up security in depth against the architecture
and vector of your typical worm.
>Why was slammer so successfull... Well... Here's my oppinion: Sysadmins
>experienced in windows usually have little firewalling skills. That's
>probably because there is no powerfull firewalling tool like ipfw or
>ipchains on windows. If all the SQL ports would have been firewalled the
>worm would probably wouldn't have caused any harm.
I believe this point needs to be corrected- Shipped since Win2k, the IPSec
policy manager can be used as a powerful firewall tool if you so
desire. It is highly configurable, can be set up via command line like
ipchains or gui like the firewall config on Linux, can be set remotely via
the MMC plug in, or deployed in the Enterprise via group policy and
organizational units. And that is just part of the power of the tools
aside from their primary purpose of maintaining IPSec tunnelling
policies. It also supports a more expanded protocol list than ipchains
(just tcp, udp, and icmp) with additional protocols like RDP, HMP, RAW, etc.
I don't know your criteria for suggesting Windows folks "usually" have
little firewalling skills, but if that is indeed true, it is not because of
Windows. All my peeps use IPSec extensively.
Besides, SQL Server is not an application where one would normally
implement host-based port firewalling; not without breaking other things,
anyway. Localized host-based hardening is fine for net-facing web servers
and DNS boxes, but SQL Server should not be directly on the net in the
first place. It was more of an infrastructure issue where these boxes
could be reached on UDP 1434; host-based firewalling was not the answer:
strong border -> DMZ firewalling policy was the answer (in addition to
patch management.)
T
-----BEGIN PGP SIGNATURE-----
Version: PGP 7.1
iQA/AwUBPkGzlohsmyD15h5gEQLtGACfbIK5quvBDn/A0X5hz3/o3a4//hoAoNz8
Bd/++Ep/uRekp9WkHI6BYyWx
=J8fv
-----END PGP SIGNATURE-----
Richard Moore
06/02/03, 19:55
Seth Breidbart wrote:
> In theory, it's easy to prove that some programs cannot be relocated,
> period. Anybody who has been programming long enough has seen people
> re-use a memory location as both an address and a constant in order to
> keep the program small enough (12k OK; 12k + 2 bytes really bad
> news). That can't be relocated.
>
> Even under the assumption that locations aren't re-used, it's provably
> impossible (Turing-complete) to determine whether the contents of a
> location can be used as an address by a program.
Sure, that is a basic corollary of the Von-Neuman programming model
(whereby a program is simply a type of data). However, it is possible to
make this untrue if you modify the model slightly to make memory areas
that are executable unreadable. Of course you are then no longer running
on a Von-Neuman machine, so the Turing machine abstraction breaks down
somewhat. Unfortunately it is difficult to acheive this with modern CPUs
and even were it to be possible, there does need to be a part of the
system somewhere that can read/write to these segments in order to
handle the loading of shared libraries etc.
Cheers
Rich/
>
> That said, _if_ a program is relocatable, relocating it would seem to
> be an easy way to gain some security. Whether that's worth the cost
> (in fragility and undebuggability) is another question.
>
> Seth
>
Seth Breidbart
06/02/03, 20:01
In theory, it's easy to prove that some programs cannot be relocated,
period. Anybody who has been programming long enough has seen people
re-use a memory location as both an address and a constant in order to
keep the program small enough (12k OK; 12k + 2 bytes really bad
news). That can't be relocated.
Even under the assumption that locations aren't re-used, it's provably
impossible (Turing-complete) to determine whether the contents of a
location can be used as an address by a program.
That said, _if_ a program is relocatable, relocating it would seem to
be an easy way to gain some security. Whether that's worth the cost
(in fragility and undebuggability) is another question.
Seth
Ilya Dubinsky
07/02/03, 17:41
IMHO, this is not possible at all.
Take a program that uses machine code for a jump instruction as both
data value and code instruction. Clearly it can't be relocated under any
circumstances without modifying its code.
Also, an algorithm to decide whether the code can be relocated can be
reduced to the halting problem:
Suppose we have such an algorithm.=20
The algorithm must distinguish between data embedded in the program and
actual code (if you have a data value which is also machine code to jump
instruction, it shouldn't be touched). So the algorithm will also have
to determine whether a jump instruction is ever reached.
=20
It is easy to see that every program can be written in a relocatable
way.
Now take such a program P and an input, make a program Q that calls P
with the input.=20
Place jump instruction to somewhere in the end of Q. Use the very same
jump instruction as a data value at the beginning of Q. Call this new
program Q'.
Now run the algorithm on Q'.
If the jump instruction is reached, Q' can't be relocated, but it means
that P stops on the given input.
If it is not reached, and because P is relocatable, Q' is relocatable
too, but it means that P doesn't stop on the given input.
This completes the reduction and the proof that such a utility is
impossible to build in proper way.
-----Original Message-----
From: Bugtraq User [mailto:bq@soft-analysts.com]=20
Sent: Thursday, February 06, 2003 12:43 AM
To: David Litchfield
Subject: Re: Preventing exploitation with rebasing
> Going back to exe image files and rebasing. Surely they can be rebased
even
> without a .reloc section? All I need to do is edit the image base in
the PE
> header then parse the assembly looking for absolute addresses such as
> function addresses, static variables etc and modify these addresses,
too.
>=20
I'm sorry but I don't think this is feasible in real life. In a test=20
program it may seem possible, but try and apply it to a real PE
executable=20
that actually does something and you will see that it is not. To even=20
begin to do what you suggest, you would need to:
1) Write a functional disassembler that understands instruction=20
boundaries and knows which instructions reference absolute addresses=20
(easy).
2) Understand parts of the code section that are not assembly=20
instructions, such as JMP tables used by switch statements, and similar=20
constructs (getting harder).
3) Understand and be able to predict unknown data types, or infer their=20
data type by where they may or may not be referenced within code (quite=20
difficult).
How do you know if \x44\x42\x41\x00 within a .data section is an
absolute=20
address 0x414244 or if it is actually the string DBA\0?
For all that effort, you might as well develop a more worthwhile
security=20
measure.
Carolyn Meinel
07/02/03, 17:49
On Wednesday 05 February 2003 16:07, Seth Breidbart wrote:
> Even under the assumption that locations aren't re-used, it's
> provably impossible (Turing-complete) to determine whether the
> contents of a location can be used as an address by a program.
Would that be more accurately not impossible, but "intractable"? With a=20
small enough and simple enough program it is possible to analyze=20
whether its implementation on a Turing Machine will reach a halting=20
point. What the Turing Machine Halting Problem proves is that for an=20
arbitrary tape, calculation of the upper bound on the number of moves=20
the read-write head must make to determine whether there is a halting=20
state is an "intractable" problem.
What this rebasing discussion comes down to is: to what extent may one=20
simplify operation of a program by limiting inputs by obfuscating ports=20
(as defined in finite state machine theory, a subset of the Turing=20
Machine) that could accept input of exploits?
Better yet, how about eliminating buffer overflow-generated ports by=20
using a programming language that doesn't automagically lend itself to=20
buffer overflows? There are, after all, languages other than C and=20
Fortran, and memory is no longer ferrite cores strung together with=20
copper wires by Taiwanese ladies and leased, not sold, by IBM. So we=20
don't really need the extreme and bug-prone measures of yesteryear to=20
save on RAM use.
Using more modern languages can also reduce the temptation to reuse=20
crufty code:)
Two excellent books relevant to this discussion are "Building Secure=20
Software" by Viega and McGraw, and "Computers and Intractability" by=20
Garey and Johnson.
--=20
"I see in the near future a crisis approaching that unnerves me and=20
causes me to tremble for the safety of my country. As a result of the=20
war, corporations have been enthroned and an era of corruption in high=20
places will follow, and the money power of the country will endeavor to=20
prolong its reign by working on the prejudices of the people until all=20
wealth is aggregated in a few hands, and the Republic is destroyed."
-- Abraham Lincoln in a letter to William F. Elkins, Nov 21st, 1864
505-281-9675
http://techbroker.com
http://happyhacker.org
Gravity. It's not just a good idea. It's the law.
Jason Coombs
07/02/03, 17:55
We expect software developers to test their products before shipping them,
but we don't require any proof they have done so. If the developer has never
executed each potential path through their code, why should we run it as
field testers when our desire instead is to be customers who rely on
trustworthy products?
As customers we should not pay for products that are being tested on us. We
should pay for products that have already been tested, and we should be
given the results of that testing to use as a tool of security auditing and
threat containment.
A system of forensic profiling for compiled code would enable numerous
countermeasures to the threats that arise today out of the necessity to
leave our microprocessors and OS APIs open to arbitrary utilization. These
resources can and should be closed to the run-time execution of code that
does not have an accompanying forensic profile created by the developer as
they carefully tested each logical path through the authentic compiled
product.
With such a fundamental shift in the way that we receive and use software
from developers, rebasing and other techniques to randomize the run-time
execution environment would be unnecessary because we would have the tools
and the information necessary to reign in our microprocessors and OS APIs.
Arbitrary malicious code can cause a CPU to do math, but it can't cause a
CPU to do harm unless it is able to communicate with or control a willing
victim (such as a device driver).
Jason Coombs
jasonc@science.org