NavigationUser login |
Reversing QT applications - Part IDamn.. this one remained in oblivion for years!.. This essay is about QT (@ trolltech) runtime debugging. It's the first of 2 articles about qt runtime manipulation. In this one we get a tree of objects from a qt applicatión, locating their main structure address memory pool. Once located a widget enable or disable buttons or menu items is a simple task. This little tool called qtree when attached to a qt application (tested in qt2.x and qt3.x) will dump it's objets tree. Now it may be outdated, as qt is now free. Introduction I'll asume the basics about qwidgets (qt programming). C++ and gdb skills are also a requisite, as some steps relay in them. In order to generate a tree with the controls of an application there are several steps to walk.. QT reversing stuff could be Download from here: qtrev-doc-src.tar.gz Parent and childs Let's focus at qwidget class for this topic (see qt documentation for help). Any widget can have one (and only one) parent, while at the same time can hold several childs. That's the nature of a qt application GUI. A fragment of qobject-h.html, inherited by qwidget class, holds parent and childs members declarations of a widget (private section of class) : ... static QMetaObject *metaObj; const char *objname; QObject *parentObj; QObjectList *childObjects; QSignalDict *connections; ...QObject class export methods for these members (qobject.html): QObject * QObject::parent () const Returns a pointer to the parent object. See also: children(). const QObjectList * QObject::children () const Returns a list of child objects, or 0 if this object has no children.The QObjectList class is defined in the qobjcoll.h header file. The latest child added is the first object in the list and the first child is added is the last object in the list. Note that the list order might change when widget children are raised or lowered. A widget that is raised becomes the last object in the list. A widget that is lowered becomes the first object in the list. See also: queryList(), parent(), insertChild() and removeChild(). We can get from the widget his parent directly reading the pointer *parentObj, as it only can have one. But for childs, we'll need to go trough a complete list of them reading each entry of childObjects. So, in order to continue, let's see how the QObjectList class work once compiled. Qt list interface The QObjectList class (see qobjectlist.h for more info) is an overloaded QList class of QObjects. Also, QList inherits QGList as main collections interface. This is the most important fragment (private declaration of qglistclass at qglist-h.html): ... QLNode *firstNode; // first node QLNode *lastNode; // last node QLNode *curNode; // current node int curIndex; // current index uint numNodes; // number of nodes QGList *iterators; // list of iterators ... What we found here is a fast access to list items, and also a new list to iterators. The fast access interface (firstNode, curNode, lastNode pointers and curIndex) will allow as to read the whole list of items. We can't relay in iterators member as it may be uninitialized. Each member of a list is a QLNode class. List nodes in qglist class The extract form qglist-h.html: ... QCollection::Item data QLNode *prev; QLNode *next; ...QCollection::Item data is the answer we are looking for: it's the pointer to the object in the memory (a pointer to a widget lstructure layout as seen in basics). That's, it's the stored item in the list. Let's go further.. Debugging aproach.. Ok, let's start with a very simple example. Time to go into qt2-doc directory and enter t4 example's (usally /usr/share/at2-doc/tutorial/t4/ ) one. If we edit the main.cpp file, we can see something like:
...
class MyWidget : public QWidget
{
public:
MyWidget( QWidget *parent=0, const char *name=0 );
};
MyWidget::MyWidget( QWidget *parent, const char *name )
: QWidget( parent, name )
{
setMinimumSize( 200, 120 );
setMaximumSize( 200, 120 );
QPushButton *quit = new QPushButton( "Quit", this, "quit" );
...
Let's modify it and leave like this one, so you could rapidly move betwen several objects in memory with the same structure:
...
QPushButton *quit;
QPushButton *quit1;
QPushButton *quit2;
QPushButton *quit2;
class MyWidget : public QWidget
{
public:
MyWidget( QWidget *parent=0, const char *name=0 );
};
MyWidget::MyWidget( QWidget *parent, const char *name )
: QWidget( parent, name )
{
setMinimumSize( 200, 120 );
setMaximumSize( 200, 120 );
quit = new QPushButton( "Quit", this, "quit" );
quit1 = new QPushButton( "Quit", quit, "quit1" );
quit2 = new QPushButton( "Quit", quit, "quit2" );
quit3 = new QPushButton( "Quit", quit, "quit3" );
...
Can you see the main diferences?, Controls quit, quit1, quit2 and quit3 are now declared for global access (.data section instead of heap) and quit1, quit2 and quit3 have been declared to be childs of widget quit (see QPushButton constructor por more info). Compile the current project (make?). Disassemble the binary (objdump), and try to locate where in the MyWidget::MyWidget function are created each one of controls quit*. Possible reference to string: "Salir" 0804aae4 push $0x804b1a4 0804aae9 lea 0xfffffffc(%ebp),%eax 0804aaec push %eax 0804aaed mov %eax,%esi Reference to function : __7QStringPCc 0804aaef call 0804a4a4 Possible reference to string: "quit" 0804aaf4 push $0x804b1aa 0804aaf9 push %edi 0804aafa push %esi 0804aafb push %ebx Reference to function : __11QPushButtonRC7QStringP7QWidgetPCc 0804aafc call 0804a334 0804ab01 movb $0x0,0xfffffff7(%ebp) 0804ab05 mov %eax,0x804c9e0 0804ab0a add $0x30,%espThe above code belongs to the statment: quit = new QPushButton( "Salir", this, "quit" ); First, a QString is created for the 'caption' member in the widget at 0x0804aaefh (see previous code listing), later, the QString pointer and the control name are pushed for creating the QPushButton at 0x0804aafch Debugging time. The goal is to examine de data of the widget after it's creation, to get the real offsets of the parentObj and childOjects members. We'll take care about it's memory layout everytime any of the other quit* controls are being created. So we break at 0x0804ab0a (see previous code listing) and examine the data at quit (is a global, gdb should work) quit+0*uint:0x8067a50: 0x2d300a2d 0x08065a40 0xbffff984 0x00000000 quit+4*uint:0x8067a60: 0x00000000 0x00000000 0x00000000 0x00000000We get at quit+8 the QOject *parentObj pointer, that's where the quit's parent memory layout is located. Next step is to create the quit1 PushButton, using quit as his parent ( next call to __11QPushButtonRC7QStringP7QWidgetPCc in the disassemble of file ). Once created, the childObjects member of quit object has to include at least 1 item. We'll locate where the pointer is examining quit's layout again: quit+0*uint:0x8067a50: 0x2d300a2d 0x08065a40 0xbffff984 0x08069f30 quit+4*uint:0x8067a60: 0x00000000 0x00000000 0x00000000 0x00000000See what's now at quit+0xc (it's supossed to be QobjectList *childOjects): 0x8069f30: 0x00000000 0x404aa4c0 0x08069f58 0x08069f58 0x8069f40: 0x08069f58 0x00000000 0x00000001 0x00000000Let's break again after next creation, just after call to create quit2, and see what changes on this QObjectList structure: 0x8069f30: 0x00000000 0x404aa4c0 0x08069f58 0x0806a950 0x8069f40: 0x0806a950 0x00000001 0x00000002 0x00000000By comparing the two dumps, we start our conclusion with this structure: 0x8069f30: Unknown Methods[] *firstNode *lastNode 0x8069f40: *currNode *currIndex *numNodes *IteratorsIf it's correct, the creation of next pushbutton (quit3) must modify the values: numNodes (increased by one), currIdenx (increased by one), currNode (new value) and lastNode (new value is = currNode). Break at end of quit3 creation and dump again: 0x8069f30: 0x00000000 0x404aa4c0 0x08069f58 0x0806aba8 0x8069f40: 0x0806aba8 0x00000002 0x00000003 0x00000000Now that we have access to the QobjectList *childObjects list of the widget, let's read a single node, for example the current (currNode) one: 0x806aba8: 0x0806aae0 0x0806a950 0x00000000 0x00000019We have to stamp then the layout of a QLNode structure: 0x806aba8: Item:0x0806aae0 prev:0x0806a950 next:0x00000000If we remember the order of the list, numIndex tells that we're on the last widget (as numNodes is 3, we are in node 2 of a 0 indexed list), so there's no next item in the list. Let's dump previous node: 0x806a950: Item:0x0806a888 prev:0x08069f58 next:0x0806aba8As we can see, the next node is where we came from. Let's go to next Node: 0x8069f58: Item:0x08069e68 prev:0x00000000 next:0x0806a950Again, next node is where we came from, and now there's no previous node. All seems to go ok as we have 3 nodes in the list, just the value of numNodes. And, what the item values are?. Easy to answer.. the values are just the offsets in memory where holds the 3 widgets: quit1, quit2 and quit3: (gdb output) (gdb) p /x quit1 = 0x8069e68 (gdb) p /x quit2 = 0x806a888 (gdb) p /x quit3 = 0x806aae0Let's complete a little the gathered information. Go back to QObject structure and you can see a member called objname (const char *). Lets get the quit2 item from the list, value 0x806a88 and dump to see it's objname pointer: quit2+0*uint:0x806a888: 0x00000200 0x0806a940 0x08068910 0x00000000 quit2+4*uint:0x806a898: 0x00000000 0x00000000 0x00000000 0x00000000 *string:0x806a940: "quit2"Now we have the name of the control. objnames are only for debugging porpouses and future qt GUI desing applications as mentioned in qt documentation. I think this could be enought in research for the qtree application, so let's start programming. building the tree Really it's now easy to do, as we can collect all the information from one widget relating to it's parent and childs. The main process must:
The most important task here is a successfull read operation from QObjectList *childObjects. For that we assume that the list state is as at generation time. The las item added is the first item in list, and currentNode is the last one. So we can go trough nodes reading the QLNode *prev member untill an invalid one is found. The rest is how to show collected information, but it's more a programming task then a reverse enginering matter, so it won't be explained here. qtree, the application I have also developed an application that do the explained above as part of a (never published and never will) toolset for qt reversing. qtree builds the widget tree from an application acepting several options in the command line. This is the download link: qtrev-doc-src.tar.gz It includes a readme file that you must read before blaming in flames about why it doesn't work for you. In order to work i've assumed a lot as initial state, so operation will success only if (and only):
Start a qt (version 2.x) application and attach qtree to it's pid. This is the result of one of the examples (the tutorial one, at last stage: t14, see an image here) included in the qt documentation: locating parent.. [0xbffff978] +[0x8075888] +[0x8075ed8] +[0x8075bc0] +[0x8075068] +[shotsleftLabel:0x8074dd0] +[hitsLabel:0x8074b48] +[shotsleft:0x80748b0] +[hits:0x8074650] +[newgame:0x80742e8] +[shoot:0x8073fb8] +[cannonFrame:0x80731a0] +[cannonField:0x8073650] +[cannonFrame:0x8073310] +[force:0x8072360] +[label:0x8072d18] +[slider:0x8072ab0] +[lcd:0x8072828] +[force:0x80724e8] +[angle:0x8070258] +[label:0x80710f8] +[slider:0x8070e90] +[lcd:0x8070c08] +[angle:0x8070458] +[quit:0x806d1a0] (I had to resize window (-s700) for a correct search as the value is being found before in the stack) There you can see the names of the widgets and it's offset within the application's memory layout. This offset is a interesting starting point when you want to modify the application GUI. All widget data (main structure) is stored there, incluiding properties (hidden, enabled, and so) and also callbacks to the widget (when clicked, pressed...), so from here you can go fast in qt reversing an application. There's another tutorial about that in this site.. the next step. FYE.. I've included some trees of known applications: kcalc lin: 403e6000-40867000 r-xp 00000000 03:03 137233 /usr/lib/libqt.so.2.3.1 badd: 0x403e6000 lib: /usr/lib/libqt.so.2.3.1 forced parent search.. widget at 0x80733e8 has no parent. Assuming root widget.. [0x40044060 : 0x80733e8] +[QVBoxLayout unnamed : 0x808b068] +[QHBoxLayout unnamed : 0x808ae90] +[QHBoxLayout unnamed : 0x808acb8] +[QHBoxLayout unnamed : 0x808aae0] +[QHBoxLayout unnamed : 0x808a940] +[QWidget unnamed : 0x8080b80] +[QGridLayout unnamed : 0x808a528] +[QPushButton modbutton : 0x8089e58] +[QPushButton OneComplementbutton : 0x8089b40] +[QPushButton percentbutton : 0x8089828] +[QPushButton equalbutton : 0x8089510] +[QPushButton 0button : 0x8089210] +[QPushButton periodbutton : 0x8088ef8] +[QPushButton shiftbutton : 0x8088bf0] +[QPushButton minusbutton : 0x80888e8] +[QPushButton plusbutton : 0x80885d0] +[QPushButton 3button : 0x80882c0] +[QPushButton 2button : 0x8087fb0] +[QPushButton 1button : 0x8087ca0] +[QPushButton orbutton : 0x80879a0] +[QPushButton divisionbutton : 0x8087688] +[QPushButton Multiplybutton : 0x8087378] +[QPushButton 6button : 0x8087068] +[QPushButton 5button : 0x8086d58] +[QPushButton 4button : 0x8086a48] +[QPushButton andbutton : 0x8086748] +[QPushButton parenclosebutton : 0x8086430] +[QPushButton parenopenbutton : 0x8086118] +[QPushButton 9button : 0x8085e08] +[QPushButton 8button : 0x8085af8] +[QPushButton 7button : 0x80857e8] +[QPushButton ACbutton : 0x80854e8] +[QPushButton Clearbutton : 0x80851d0] +[QPushButton MCbutton : 0x8084ed0] +[QPushButton Mplusminusbutton : 0x8084bb8] +[QPushButton MRbutton : 0x80848a8] +[QPushButton EEbutton : 0x8084528] +[QWidget unnamed : 0x80809d0] +[QGridLayout unnamed : 0x808a158] +[QPushButton Fbutton : 0x8084228] +[QPushButton powerbutton : 0x8083f10] +[QPushButton lnbutton : 0x8083c00] +[QPushButton Ebutton : 0x8083900] +[QPushButton squarebutton : 0x80835e8] +[QPushButton logbutton : 0x80832d8] +[QPushButton Dbutton : 0x8082fd8] +[QPushButton factorialbutton : 0x8082cc0] +[QPushButton Tanbutton : 0x80829b0] +[QPushButton Cbutton : 0x80826b0] +[QPushButton recibutton : 0x8082398] +[QPushButton Cosbutton : 0x8082088] +[QPushButton Bbutton : 0x8081d88] +[QPushButton plusminusbutton : 0x8081a70] +[QPushButton Sinbutton : 0x8081760] +[QPushButton Abutton : 0x8081450] +[QPushButton InverseButton : 0x8081140] +[QPushButton hypbutton : 0x8080d78] +[QButtonGroup base : 0x807d280] +[QRadioButton unnamed : 0x807fec0] +[QAccel buttonAccel : 0x8080428] +[QRadioButton unnamed : 0x807f3b0] +[QAccel buttonAccel : 0x807f918] +[QRadioButton unnamed : 0x807e870] +[QAccel buttonAccel : 0x807edd8] +[QRadioButton unnamed : 0x807dcf8] +[QAccel buttonAccel : 0x807e2a8] +[QVBoxLayout unnamed : 0x807d498] +[QGridLayout unnamed : 0x807d818] +[QButtonGroup angle : 0x8079fd8] +[QRadioButton unnamed : 0x807c770] +[QAccel buttonAccel : 0x807ccd8] +[QRadioButton unnamed : 0x807bc60] +[QAccel buttonAccel : 0x807c1c8] +[QRadioButton unnamed : 0x807b028] +[QAccel buttonAccel : 0x807b5c8] +[QVBoxLayout unnamed : 0x807a238] +[QGridLayout unnamed : 0x807a8d8] +[QLabel ERROR : 0x8079d78] +[QLabel HYP : 0x8079b18] +[QLabel INV : 0x80798d8] +[0x40044500 display : 0x8078ec0] +[QPushButton helpbutton : 0x8078bb8] +[QPushButton configbutton : 0x8077518] +[QAccel unnamed : 0x8075628]and also kmix lin: 403ba000-4083b000 r-xp 00000000 03:03 137233 /usr/lib/libqt.so.2.3.1 badd: 0x403ba000 lib: /usr/lib/libqt.so.2.3.1 [0x8064900 : 0x80a4570] +[QSlider RightLeft : 0x80e1cf0] +[0x80651a0 Video : 0x80dd110] +[0x4037cfa0 Keys : 0x80e0f68] +[QTimer unnamed : 0x80e0da0] +[0x8064f80 RecordLED : 0x80e0980] +[QSlider Video : 0x80e04a0] +[QSlider Video : 0x80dff98] +[0x8064f80 MuteLED : 0x80df8a8] +[QLabel unnamed : 0x80df488] +[QLabel unnamed : 0x80def88] +[QVBoxLayout unnamed : 0x80decf0] +[QHBoxLayout unnamed : 0x80dfd50] +[0x40203260 : 0x80dd368] +[0x40203e20 keys : 0x80de978] +[0x40203d20 recsrc : 0x80de598] +[0x40203e20 show_all : 0x80de220] +[0x40203d20 mute : 0x80ddec8] +[0x40203e20 hide : 0x80ddb68] +[0x40203d20 stereo : 0x80dd778] +[0x80651a0 PhoneOut : 0x80d92f8] +[0x4037cfa0 Keys : 0x80dc430] +[QTimer unnamed : 0x80dc2b8] +[QSlider PhoneOut : 0x80dbdb0] +[0x8064f80 MuteLED : 0x80db6c0] +[QLabel unnamed : 0x80db2a0] +[QLabel unnamed : 0x80dada0] +[QVBoxLayout unnamed : 0x80dab08] +[QHBoxLayout unnamed : 0x80dbb68] +[0x40203260 : 0x80d9550] +[0x40203e20 keys : 0x80da688] +[0x40203e20 show_all : 0x80da408] +[0x40203d20 mute : 0x80da0b0] +[0x40203e20 hide : 0x80d9d50] +[0x40203d20 stereo : 0x80d9960] +[0x80651a0 PhoneIn : 0x80d4c30] +[0x4037cfa0 Keys : 0x80d85a8] +[QTimer unnamed : 0x80d83e0] +[0x8064f80 RecordLED : 0x80d7fc0] +[QSlider PhoneIn : 0x80d7ab8] +[0x8064f80 MuteLED : 0x80d73c8] +[QLabel unnamed : 0x80d6fa8] +[QLabel unnamed : 0x80d6aa8] +[QVBoxLayout unnamed : 0x80d6810] +[QHBoxLayout unnamed : 0x80d7870] +[0x40203260 : 0x80d4e88] +[0x40203e20 keys : 0x80d6498] +[0x40203d20 recsrc : 0x80d60b8] +[0x40203e20 show_all : 0x80d5d40] +[0x40203d20 mute : 0x80d59e8] +[0x40203e20 hide : 0x80d5688] +[0x40203d20 stereo : 0x80d5298] +[0x80651a0 Line1 : 0x80d0088] +[0x4037cfa0 Keys : 0x80d3ee0] +[QTimer unnamed : 0x80d3d18] +[0x8064f80 RecordLED : 0x80d38f8] +[QSlider Line1 : 0x80d3418] +[QSlider Line1 : 0x80d2f10] +[0x8064f80 MuteLED : 0x80d2820] +[QLabel unnamed : 0x80d2400] +[QLabel unnamed : 0x80d1f00] +[QVBoxLayout unnamed : 0x80d1c68] +[QHBoxLayout unnamed : 0x80d2cc8] +[0x40203260 : 0x80d02e0] +[0x40203e20 keys : 0x80d18f0] +[0x40203d20 recsrc : 0x80d1510] +[0x40203e20 show_all : 0x80d1198] +[0x40203d20 mute : 0x80d0e40] +[0x40203e20 hide : 0x80d0ae0] +[0x40203d20 stereo : 0x80d06f0] +[0x80651a0 IGain : 0x80cb4e0] +[0x4037cfa0 Keys : 0x80cf338] +[QTimer unnamed : 0x80cf170] +[0x8064f80 RecordLED : 0x80ced50] +[QSlider IGain : 0x80ce870] +[QSlider IGain : 0x80ce368] +[0x8064f80 MuteLED : 0x80cdc78] +[QLabel unnamed : 0x80cd858] +[QLabel unnamed : 0x80cd358] +[QVBoxLayout unnamed : 0x80cd0c0] +[QHBoxLayout unnamed : 0x80ce120] +[0x40203260 : 0x80cb738] +[0x40203e20 keys : 0x80ccd48] +[0x40203d20 recsrc : 0x80cc968] +[0x40203e20 show_all : 0x80cc5f0] +[0x40203d20 mute : 0x80cc298] +[0x40203e20 hide : 0x80cbf38] +[0x40203d20 stereo : 0x80cbb48] +[0x80651a0 CD : 0x80c6818] +[0x4037cfa0 Keys : 0x80ca790] +[QTimer unnamed : 0x80ca5c8] +[0x8064f80 RecordLED : 0x80ca1a8] +[QSlider CD : 0x80c9cc8] +[QSlider CD : 0x80c97c0] +[0x8064f80 MuteLED : 0x80c90d0] +[QLabel unnamed : 0x80c8cb0] +[QLabel unnamed : 0x80c8690] +[QVBoxLayout unnamed : 0x80c83f8] +[QHBoxLayout unnamed : 0x80c9578] +[0x40203260 : 0x80c6a70] +[0x40203e20 keys : 0x80c8080] +[0x40203d20 recsrc : 0x80c7ca0] +[0x40203e20 show_all : 0x80c7928] +[0x40203d20 mute : 0x80c75d0] +[0x40203e20 hide : 0x80c7270] +[0x40203d20 stereo : 0x80c6e80] +[0x80651a0 Microphone : 0x80c2008] +[0x4037cfa0 Keys : 0x80c5ac8] +[QTimer unnamed : 0x80c5900] +[0x8064f80 RecordLED : 0x80c54e0] +[QSlider Microphone : 0x80c4fd8] +[0x8064f80 MuteLED : 0x80c48e8] +[QLabel unnamed : 0x80c44c8] +[QLabel unnamed : 0x80c3e80] +[QVBoxLayout unnamed : 0x80c3be8] +[QHBoxLayout unnamed : 0x80c4d90] +[0x40203260 : 0x80c2260] +[0x40203e20 keys : 0x80c3870] +[0x40203d20 recsrc : 0x80c3490] +[0x40203e20 show_all : 0x80c3118] +[0x40203d20 mute : 0x80c2dc0] +[0x40203e20 hide : 0x80c2a60] +[0x40203d20 stereo : 0x80c2670] +[0x80651a0 Line : 0x80bd460] +[0x4037cfa0 Keys : 0x80c12b8] +[QTimer unnamed : 0x80c10f0] +[0x8064f80 RecordLED : 0x80c0cd0] +[QSlider Line : 0x80c07f0] +[QSlider Line : 0x80c02e8] +[0x8064f80 MuteLED : 0x80bfbf8] +[QLabel unnamed : 0x80bf7d8] +[QLabel unnamed : 0x80bf2d8] +[QVBoxLayout unnamed : 0x80bf040] +[QHBoxLayout unnamed : 0x80c00a0] +[0x40203260 : 0x80bd6b8] +[0x40203e20 keys : 0x80becc8] +[0x40203d20 recsrc : 0x80be8e8] +[0x40203e20 show_all : 0x80be570] +[0x40203d20 mute : 0x80be218] +[0x40203e20 hide : 0x80bdeb8] +[0x40203d20 stereo : 0x80bdac8] +[0x80651a0 Speaker : 0x80b9528] +[0x4037cfa0 Keys : 0x80bc780] +[QTimer unnamed : 0x80bc608] +[QSlider Speaker : 0x80bc100] +[0x8064f80 MuteLED : 0x80bba10] +[QLabel unnamed : 0x80bb5f0] +[QLabel unnamed : 0x80bafd0] +[QVBoxLayout unnamed : 0x80bad38] +[QHBoxLayout unnamed : 0x80bbeb8] +[0x40203260 : 0x80b9780] +[0x40203e20 keys : 0x80ba8b8] +[0x40203e20 show_all : 0x80ba638] +[0x40203d20 mute : 0x80ba2e0] +[0x40203e20 hide : 0x80b9f80] +[0x40203d20 stereo : 0x80b9b90] +[0x80651a0 Pcm : 0x80b5110] +[0x4037cfa0 Keys : 0x80b8848] +[QTimer unnamed : 0x80b86d0] +[QSlider Pcm : 0x80b81f0] +[QSlider Pcm : 0x80b7ce8] +[0x8064f80 MuteLED : 0x80b75f8] +[QLabel unnamed : 0x80b71d8] +[QLabel unnamed : 0x80b6bb8] +[QVBoxLayout unnamed : 0x80b6920] +[QHBoxLayout unnamed : 0x80b7aa0] +[0x40203260 : 0x80b5368] +[0x40203e20 keys : 0x80b64a0] +[0x40203e20 show_all : 0x80b6220] +[0x40203d20 mute : 0x80b5ec8] +[0x40203e20 hide : 0x80b5b68] +[0x40203d20 stereo : 0x80b5778] +[0x80651a0 Volume : 0x80a7618] +[0x4037cfa0 Keys : 0x80b41e0] +[QTimer unnamed : 0x80b4068] +[QSlider Volume : 0x80b3b88] +[QSlider Volume : 0x80b31f8] +[0x8064f80 MuteLED : 0x80b27a8] +[QLabel unnamed : 0x80b2388] +[QLabel unnamed : 0x80b1618] +[QVBoxLayout unnamed : 0x80b1380] +[QHBoxLayout unnamed : 0x80b2fb0] +[0x40203260 : 0x80afe78] +[0x40203e20 keys : 0x80b0f00] +[0x40203e20 show_all : 0x80b0c80] +[0x40203d20 mute : 0x80b0928] +[0x40203e20 hide : 0x80a2e50] +[0x40203d20 stereo : 0x80a29f0] +[QVBoxLayout unnamed : 0x80a4d18] +[QHBoxLayout unnamed : 0x80a89d8] +[0x40203260 : 0x80a3dc8] +[0x40203e20 show_all : 0x80a8598] |
SearchSyndicate |