Форум: "Потрепаться";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 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




Форум: "Потрепаться";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.25;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.75 MB
Время: 0.018 c
14-81041          vlv                   2002-03-19 18:50  2002.04.25  
База данных - слова


3-80832           Tolstomordik          2002-04-05 17:12  2002.04.25  
Получить значение выбранной ячейки в DBGrid


3-80745           saperxl               2002-04-04 01:19  2002.04.25  
Простенький вопрос мастерам


4-81116           Song                  2002-02-19 17:08  2002.04.25  
WM_POWERBROADCAST отловить жд. режим и обратно


1-80885           Ray_Parker            2002-04-12 17:41  2002.04.25  
Вопрос по обработке события OnKeyUp