Форум: "Потрепаться";
Текущий архив: 2002.04.25;
Скачать: [xml.tar.bz2];
Внизопределить адрес процедуры из нее самой Найти похожие ветки
← →
MBo (2002-03-18 16:13) [0]В конференции Borland встретился вопрос (вообще-то, по моему, нелепый), сводящийся к тому, как определить Subj.
Получилось у меня так:
procedure TForm1.Button1Click(Sender: TObject);
var p:pbyte;
function DummyFunc: Pointer;
asm
xor eax, eax
end;
begin
p:=@DummyFunc;
inc(p,4);
label3.caption:=classname+"."+methodname(p);
end;
Но более радикально было бы для этого вызывать внешнюю по отношению к данной процедуре функцию.
function ACaller:pointer;
asm
mov eax, [esp]
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
var p,p1:pbyte;
begin
p1:=ACaller;
dec(p1,53);//Magic Number
p:=methodaddress("CheckBox1Click");//для контроля
label3.caption:=inttohex(cardinal(p),8);
label4.caption:=inttohex(cardinal(p1),8);
label2.caption:=classname+"."+methodname(p1);
end;
Так работает, но Magic Number, естественно, зависит от пролога данной процедуры и может меняться. Полагаю, методы для subj можно найти,(кроме methodaddress и @procname, естественно). Идеи есть?
← →
VuDZ (2002-03-18 16:28) [1]т.е. положение в памяти этого куска кода?
← →
VuDZ (2002-03-18 16:35) [2]кстати, почему не лепый - вот применение:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
typedef INT (proc)(VOID);
int main(){
void *v = &main;
proc *p = (proc*)v;
try{
(*p)();
}
catch (...) {
printf("Fucked stack :<\n");
}
return 0;
}
простенько и со вкусом :>
← →
MBo (2002-03-18 16:37) [3]точку входа ( в примере по ней можно найти имя метода).
т.е. адрес первого push ebp
в зависимости от того, что есть в процедуре (например, строки)
до call ACaller (когда я могу поймать esp) разное расстояние
← →
MBo (2002-03-18 16:41) [4]во-во, только мне интересно без void *v = &main - т.е. явного указания
← →
VuDZ (2002-03-18 16:51) [5]нате:
int main(){
_asm{
call next;
next:
pop eax;
sub eax, 0x1d;
call eax;
}
return 0;
}
← →
MBo (2002-03-18 16:58) [6]нечто вроде этого у меня в первом примере, только без Stack OverFlow ;)
← →
VuDZ (2002-03-18 17:06) [7]а это мой любимое :>
а зачем ещё что-то? мне приходилось пользоваться такими трюками, но только зачем это?
← →
MBo (2002-03-18 17:11) [8]просто заинтересовался ;)
← →
VuDZ (2002-03-18 17:15) [9]а слабо сделать такую фичу:
classA
member int foo();
member float doo():
classB
bool foo();
int doo();
classA A;
a->doo();
?
просто заинтерисовался...
← →
MBo (2002-03-18 17:20) [10]чем отличаются декларации с member и без него?
← →
VuDZ (2002-03-18 17:23) [11]ну в смысле у тебя есть указатель на один класс, а надо вызвать по нему методы другого класса :>
на самом деле я не помню как это звучит правильно, но делалось это через мухлёж с vtpr, и было досаточно красиво :>
сейчас попробую повторить
← →
VuDZ (2002-03-18 17:30) [12]вот пример, правда он делает не совсем то:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
typedef INT (proc)(VOID);
class A{
public:
int foo() { printf("A::foo()\n"); return 1; }
float doo(){ printf("A::doo()\n"); return 1.0; }
};
class B{
public:
bool foo(){ printf("B::foo()\n"); return false; }
float doo(){ printf("B::doo()\n"); return 0.0; }
};
int main(){
A a;
a.foo();
a.doo();
B * t = reinterpret_cast<B*>(&a);
t->doo();
return getch();
}
Результат:
B::doo() !!! хотя взято из A :>
← →
MBo (2002-03-18 17:56) [13]function TB.Foo: integer;
begin
Result:=1;
end;
function TA.Foo: integer;
begin
Result:=2;
end;
procedure TForm1.Button1Click(Sender: TObject);
var a:ta; b:tb;
pa,pb:^Pointer;
begin
a:=ta.create;
b:=tb.create;
pa:=ta.methodaddress("Foo");
pb:=tb.methodaddress("Foo");
label1.caption:=inttostr(a.foo);
pa^:=pb^;
label2.caption:=inttostr(a.foo);
в первой метке выводится 1, во второй - 2
можно и через vmtMethodTable сделать
← →
VuDZ (2002-03-19 01:51) [14]эт нето....
вот, вот такой пример, только смеяться не надо:
class A{
public:
A(int n){
m_nVal = n;
}
int foo(int);
int m_nVal;
void doo(){
printf("doo\n");
printf("m_nVal = %i\n", m_nVal);
}
};
int A::foo(int n){
printf("foo called\n");
printf("%i\n", n);
doo();
return 0;
}
class B{
public:
int i1, i2, i3, i4;
B(){
i1 = 1;
i2 = 0x2;
i3 = 0x3;
i4 = 0x4;
}
void bInit(){
i1 = 1;
i2 = 0x2;
i3 = 0x3;
i4 = 0x4;
}
double foo(){
printf("B::foo()\n");
printf("%i = i1\n", i1);
return 0.0;
}
void v(){
printf("B::v\n");
printf("%i = i2\n", i2);
}
void doo(){
printf("B::doo()\n");
printf("%i = i3\n", i3);
}
void doo2(){
printf("B::doo2()\n");
printf("%i = i4\n", i4);
}
};
class Stub{
};
int main(){
int k = 666;
B b = *reinterpret_cast<B*>(&k); // !!! from integer to class
b.bInit(); // only for variables initialization, nothing more
b.foo();
b.v();
b.doo();
b.doo2();
A n = (A)*(reinterpret_cast<A*>(&b));
n.A(1234);
n.doo();
n.foo(777);
printf("%i\n", k);
return getch();
}
PS из-за n.A(1234);, явного вызова конструктора, это соберут не все компиляторы, MS VC++ послал меня в пешее эротическое путешествие, так сильно это мотивируя, что захотело его стереть.
смысл, я думаю ясен - int -> B - > A, и всё работает, только вот переменный надо инициализировать, а то глюки могут быть. Хотя тут ничего особогои нет.
Для контроля- вывод:
B::foo()
1 = i1
B::v
2 = i2
B::doo()
3 = i3
B::doo2()
4 = i4
doo
m_nVal = 1234
foo called
777
doo
m_nVal = 1234
666
sya
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2002.04.25;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.006 c