Welcome, Guest
Welcome to Makestation! We are a creative arts/indie discussion community — Your center for creative arts discussion, unleashed!

Please note that you must log in to participate in discussions on the forum. If you do not have an account, you can create one here. We hope you enjoy the forum!

Status Updates
Avatar of User
Easy Equipment Finance November 18th, 2024
Update your status...
Avatar of User
Thomas October 24th, 2024
Update your status...
Avatar of User
Selena98 October 19th, 2024
Update your status...
Avatar of User
Thomas September 18th, 2024
what a d*** shame
Avatar of User
writingsharks August 16th, 2024
Writing Sharks is a team of professional writers that provides 100% original, high-quality, plagiarism-free content. Our services include essay writing, research paper writing, term paper writing, academic writing help, and much more. Visit today to order your writing. https://writingsharks.net/
View all updates

Search Forums

(Advanced Search)

Forum Statistics
» Members: 821
» Latest member: arhanshaikh
» Forum threads: 2,105
» Forum posts: 26,253

Full Statistics

Online Users
There are currently 479 online users.
» 0 Member(s) | 478 Guest(s)
Google

Latest Threads
Why Should You Use a Home...
Forum: Announcements
Last Post: arhanshaikh
November 26th, 2024 at 9:56 AM
» Replies: 1
» Views: 161
Forum game, I'm traveling...
Forum: Forum Games
Last Post: novavoyager
November 18th, 2024 at 9:16 PM
» Replies: 11
» Views: 7,473
Buy Bank Logs with email ...
Forum: Media & Entertainment
Last Post: MrVenus
November 14th, 2024 at 8:02 PM
» Replies: 0
» Views: 115
Buy Bank Logs with email ...
Forum: Web Design & Internet
Last Post: MrVenus
November 14th, 2024 at 8:01 PM
» Replies: 0
» Views: 98
Buy Bank Logs with email ...
Forum: General Discussion
Last Post: MrVenus
November 14th, 2024 at 8:01 PM
» Replies: 0
» Views: 105
Oh big steve.
Forum: Forum Games
Last Post: alex888
November 14th, 2024 at 5:44 PM
» Replies: 5
» Views: 3,416
Guess the movie(s) in 5 w...
Forum: Forum Games
Last Post: alex888
November 14th, 2024 at 2:25 PM
» Replies: 9
» Views: 11,352

 
  NTDLL, PEB, LDr, and F**king with Winternals
Posted by: Lain - June 14th, 2020 at 10:37 PM - Forum: Software - Replies (1)

For reference, here's the final code so you can follow along: https://pastebin.com/33uqTh84



I posted this like two days ago on a site that a friend invited me to for old time's sake, but didn't get much attention so I'll post it here for its informativity.

Long story short, another old friend of mine in the security community once challenged someone to do the following. I was more or less clueless about WinAPI and C at the time so I kept my mouth shut, but that challenge always kept itself at the back of my head whenever I wrote anything that used WinAPI to do anything.

The challenge (or rather the question) was something as follows:
Quote:How can you find the base address of kernelbase.dll as it's loaded in memory using the PEB on Windows?

So I interpreted the challenge as an opportunity to write my own little PoC to do exactly that.



PEB:

PEB is an abbreviation of a data structure present in Windows since Windows NT. The full name is the Process Environment Block, and is essentially a data structure used by the windows kernel to manage the process as its running and keep track of whatever important data is needed.

According to MSDN, the structure is defined as follows:

Code:
typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                        Reserved3[2];
  PPEB_LDR_DATA                Ldr;
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  PVOID                        Reserved4[3];
  PVOID                        AtlThunkSListPtr;
  PVOID                        Reserved5;
  ULONG                        Reserved6;
  PVOID                        Reserved7;
  ULONG                        Reserved8;
  ULONG                        AtlThunkSListPtr32;
  PVOID                        Reserved9[45];
  BYTE                          Reserved10[96];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved11[128];
  PVOID                        Reserved12[1];
  ULONG                        SessionId;
} PEB, *PPEB;

Now, take note of a couple things. First of all, lots of the data types are only listed as "Reserved" and according to MSDN, that just means it's "reserved for kernel/OS use only." In other words, they want to hide functionality, so they only tell you what SOME parts of the PEB are for.

Luckily, enough people have reversed ntdll.dll to find out exactly what all the reserved values represent, and we will encounter them later on, but as it stands, all the data we need is for the most part "open source." You'll also notice that the types for each entry aren't for the most part standard. Rather, they're all Windows internal types. PVOID actually represents a pointer to void, BYTE represents a wide char, and of course, ULONG would be an unsigned long.

The structure can also be referenced as PPEB which would be a pointer to the structure in memory. That might be useful later on.



LDR:

To be entirely honest, I have no idea what this officially stands for, I can't actually find a single post online that references its full name. My best guess would be 'Loaded Dynamic Resources' or something of that sort.

Essentially, the LDR serves as a table that keeps track of all libraries that get loaded into memory.

Take a DLL for instance.
It's a library that's been compiled. So all its functions are already in a bytecode format, and when your application tries to use a DLL file, it actually needs to load that file into memory, load the symbol table for the file as well, and find the offset of whatever function you want to call.

Kernelbase.dll is one of the DLLs that gets loaded into essentially every single application because for the kernel to do its work (or other winapi processes,) it needs to have some of its own code in there to change access tokens or retrieve handles or whatever. So ideally, we should be able to find the base address of kernelbase.dll using the LDR.

And, as we can see in the PEB data structure declaration, one of the values is of the type PPEB_LDR_DATA.

Looking at the MSDN documentation for the structure, we have the following:

Code:
typedef struct _PEB_LDR_DATA {
  BYTE       Reserved1[8];
  PVOID      Reserved2[3];
  LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

So PPEB_LDR_DATA will refer to a pointer to the structure in question. Again, might be useful to note that.

Also, OhGreatMoreReservedBullshit.png.mp3.ogg.exe.scr
Seriously, kinda pissing me off having to rely on some bloke's personal docs instead of MSDN's own.

LIST_ENTRY is probably what I'm looking for, and looking at that structure...
Code:
typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
Tells me at least a little bit.

In short: It's your regular run-of-the-mill doubly-linked list. So it's circular (i.e. the last element points forward to the first element, and the first element points backwards to the last element), Flink represents the next item in the list, and Blink represents the previous item in the list.

According to MSDN once again, each element of the LIST_ENTRY structure found in PEB_LDR_DATA should be an actual entry in the list containing a LDR_DATA_TABLE_ENTRY.

Code:
typedef struct _LDR_DATA_TABLE_ENTRY {
    PVOID Reserved1[2];
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2[2];
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
    UNICODE_STRING FullDllName;
    BYTE Reserved4[8];
    PVOID Reserved5[3];
    union {
        ULONG CheckSum;
        PVOID Reserved6;
    };
    ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

Well, there's a pretty major couple of problems with this, but we'll get to it later. Let's start writing some code.




Setting Up our Project:

Alright, I'm going to try and do everything in raw C to the best degree I can. No extra abstraction, nothing extra like streams, just Windows typedefs and structs.

I promise, the code isn't too difficult to understand, but there are a few hurdles to jump over because of Windows's closed-sourced nature and poor documentation.

First, from MSDN, the structures I mentioned above are all given in the <winternl.h> header. We're also using <Windows.h> so the kernel knows to load kernel32.dll and kernelbase.dll when we launch the program (and se we get all the types and functions we need later.)

I'm going to write everything in main() so ideally this shouldn't be too terrible for a template:

Code:
#include <stdio.h>
#include <Windows.h>
#include <Winternl.h>

int main() {

    return 0;
}

Pretty straight forward.

Now comes the first hurdle.



Dynamic Loading and Function Pointers:

So how exactly does a function get called in a program?

Basically, every function is just a segment of bytecode that the program can jump to when the function gets called. That segment also contains a ret instruction which will jump back to the address stored in EAX on 32bit systems and RAX on 64bit.

So, in short, a function is just a memory offset.
Or, in other words again, it's just a pointer to some more bytecode.

So it would make sense that we can call a function by a pointer to where that function resides in memory, right?
GladWeHaveAnUnderstanding

You see, there's a really easy way to get the address of the PEB of a process in Windows. No ASM needed, rather, there's a WinAPI function that does it for us:

Code:
__kernel_entry NTSTATUS NtQueryInformationProcess(
  IN HANDLE           ProcessHandle,
  IN PROCESSINFOCLASS ProcessInformationClass,
  OUT PVOID           ProcessInformation,
  IN ULONG            ProcessInformationLength,
  OUT PULONG          ReturnLength
);

And following documentation, if we set ProcessInformationClass to 0 (or ProcessBasicInformation), then it should return the following structure:

Code:
typedef struct _PROCESS_BASIC_INFORMATION {
    PVOID Reserved1;
    PPEB PebBaseAddress;
    PVOID Reserved2[2];
    ULONG_PTR UniqueProcessId;
    PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;

Well, would you look at that? It contains a PPEB value, which coincidentally, we already found above to be a pointer to the PEB structure.

So how does this function work?
Quote:
  • ProcessHandle (INPUT) takes in the type HANDLE for the process to try and retrieve the information about
  • ProcessInformationClass (INPUT) is the type of information to retrieve (we already specified ProcessBasicInformation which is an enum type pointing to 0)
  • ProcessInformation (OUTPUT) is a void pointer to where the structure should be stored in memory.
  • ProcessInformationLength (INPUT) should be the size of the buffer specified, so no overflows happen.
  • ReturnLength (OUTPUT) is an address to where the function should return the length of bytes written.

The return value of the function is of type NTSTATUS which is essentially a way to check error codes on old Windows functions that have been around since NT.

Now, remember how we already established functions work on computers?

The problem we run into here is that Ntdll is, well, a DLL. Yeah, I can add <Winternl.h> to get the function definitions and structures and all that, but it doesn't actually contain ANY CODE from Ntdll. So, although I can technically write the functions into my code without VisualStudio giving me a hard time, there's no easy way to actually LINK the functions from the DLL to the application.

And thus, now I need to actually load the assembled file into memory, find the function as it's loaded, then call the function.

Thank god, there are WinAPI functions that help you do that.
But first, I need to actually build the structure that the function follows.

To do so, I add the following lines between my #includes and main():

Code:
typedef NTSTATUS(__stdcall* NT_QUERY_INFO) (
    IN HANDLE           ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID           ProcessInformation,
    IN ULONG            ProcessInformationLength,
    OUT PULONG          ReturnLength
    );

NT_QUERY_INFO NtQueryInfo;

Yeah, it's basically a straight copy-paste job from what MSDN documented.
I'm grateful for at least that much from them.

Just a couple things to note: We're essentially declaring NT_QUERY_INFO as a pointer to a function that returns an NTSTATUS type, and follows the calling convention of __stdcall* (the typical calling convention of WinAPI functions compared to the typical Linux method of cdecl). Within that type, we allow it to pass the structure defined within the brackets.

You can essentially think of that line as a really complicated function prototype. But unfortunately, the compiler has no way of knowing what's being loaded since it'll be happening at runtime and not compile-time, so we need to specify all those nitty-gritty details to make sure everything works.

We then actually declare a 'variable' with that function. Or in other words, we're making a buffer to load that function into (or rather, loading a pointer to the function into.)

The compiler will handle the rest.

Now, let's load the DLL and find the function (and of course save it into our buffer we declared.
As mentioned, WinAPI provides two nice functions to help with this: LoadLibrary() and GetProcAddress().

Code:
int main() {

    //Dynamically loading NtQueryInformationProcess()...
    HMODULE hModule = LoadLibrary(TEXT("ntdll.dll"));
    NtQueryInfo = (NT_QUERY_INFO)GetProcAddress(hModule, "NtQueryInformationProcess");
    if (hModule == NULL) {
        printf("Could not find ntdll. Exiting...\n");
        return 1;
    }
    return 0;
}

Simple enough?
We load the library and get a handle (HMODULE type) with LoadLibrary(). Since LoadLibrary() takes in a type of LPCSTR instead of a normal char*, we need to also convert our normal string to that type using the TEXT() macro.

Side note: LPCSTR = Long Pointer to Const STRing
So basically, the size of the pointer to the string varies and will break the code if it doesn't match (out-of-bounds read.)

Then, we use GetProcAddress() to find the actual virtual address of the function NtQueryInformationProcess() in the loaded address space of ntdll.dll. Finally, we cast it to the type of the typedef we declared earlier (NT_QUERY_INFO) and save its address to NtQueryInfo.

Finally, to make sure the DLL was loaded properly, we have a little conditional that will break execution if it can't get a proper HANDLE from LoadLibrary().



Calling Our NT Function:

Now we have our function pointer set up.

Let's go back to our checklist of how we're supposed to find the address of kernelbase.dll:

Code:
- Retrieve the PEB
- Read LDR
----> Count number of entries in LDR since it's circular
----> Read the name and base address of each entry and get all the data we can.

And all we've done so far is just so that we could do step one and retrieve the PEB.

Oh well.
Let's call our hard work.

Code:
//Setting up the data for the call...
    HANDLE hProc = GetCurrentProcess();
    PROCESS_BASIC_INFORMATION info;
    ZeroMemory(&info, sizeof(info));
    DWORD retLength;

//Function call!
    NTSTATUS status = NtQueryInfo(hProc, ProcessBasicInformation, &info, sizeof(info), &retLength);
    if (!NT_SUCCESS(status)) {
        printf("Failed in calling NtQueryInformationProcess(). Error code: 0x%16x\n", status);
        return 1;
    }

    printf("Succeeded in calling NtQueryInformationProcess().\n");
    printf("PEB located @ 0x%016x\n\n", info.PebBaseAddress);

So, let's go down the list:
GetCurrentProcess() returns the handle of the currently-running process that the function is called from.
I opted for this instead of OpenProcess() because OpenProcess() requires specifying permissions and may run into errors. NtQueryInformationProcess requires a handle with the permissions for PROCESS_QUERY_INFORMATION. You might not be able to open a process with specific rights, so instead I opt for GetCurrentProcess() which returns a handle with PROCESS_ALL_ACCESS to ensure we don't have access problems. We save this value to hProc.

Next is the Info Class. We mentioned it's an enum type pointing to 0, but since it's declared in <winternl.h>, we can put it in there literally to make stuff easier to read.

Now, the buffer.
We've established what the structure is above, and we have the structure declaration from the header file again, so let's go ahead and just declare it.

Since memory allocation is finnicky when native, I've also opted to zero all the memory out using the ZeroMemory() macro just to make sure there's no weird residual data lying around there.

Finally, I specify a DWORD value where the ReturnLength can safely output as well. Now, I know, you're thinking "But the function call was defined to take in a PULONG type, not a DWORD!" Well, PULONG is a pointer to an unsigned long type. And funnily enough, in Windows.h, a DWORD is typedef'd as an unsigned long. So HA. We pass its address as the past parameter.

Then, we run the NTSUCCESS macro to make sure the call succeeded (remember, the NTSTATUS return type is how we check if execution succeeded or failed, and what its error code is.) So the printf() in the case of failure will give us the error code.

Otherwise, if it succeeds, we can now retrieve a pointer to the PEB from info->PebBaseAddress, and printf() that address/pointer as well.




Reading the PEB and Counting the LDR:

We have our PEB now, or at least a pointer that refers to it in memory.
Since our PEB struct declaration provided by MSDN also included PPEB as a reference, we can store the PEB as the following:

Code:
PPEB pPeb = info->PebBaseAddress;

Simple, yeah?

Now, if you're unfamiliar with the -> notation that I'm using, remember, QueryInfo returned a buffer. We're getting that buffer with a pointer. Naturally, we would need to retrieve PebBaseAddress using some weird hack like this:
Code:
(*info).PebBaseAddress
But, the arrow notation lets us implicitly tell the compiler that it's a pointer, and it'll fix itself accordingly.

To continue, we now need to actually read the PEB to find the LDR.
But that's easy, since the LDR is not one of the undocumented fields.

Rather, we can now save the pointer to the LDR as the following:
Code:
PPEB_LDR_DATA pLdr = pPeb->Ldr;
Again, just one line.

Honestly, we could combine the two to make one minified version, but I'm not a sadist. I write this shit so people can learn from it and see what mistakes I encountered and what I considered. Learn from the code, I try to make it easy to do so.

Now, like I mentioned, the LDR is basically just one big linked list of pointers to other pointers. And it's circular.

So from the LDR_DATA table, let's actually go into the table and save the first entry. Then we'll loop around until our current position becomes the same as the starting position in the table.

Code:
PLIST_ENTRY startPos = &pLdr->InMemoryOrderModuleList;
PLIST_ENTRY currPos = startPos->Flink;
int moduleCount = 0;
while (currPos != startPos) {
    moduleCount++;
    currPos = currPos->Flink;
}
printf("Found %d modules loaded.\n", modulecount);

The last and arguably most difficult problem to debug is coming very soon.

so far, we've been able to load ntdll dynamically, find a function in it and call it using a function pointer, get the address of the PEB, get the LDR table from the PEB, and find the number of modules loaded into the address space based on the number of entries in the LDR.

So even though it's about to get tough, we've gotten pretty d*** far.




Poor MSDN Documentation and Bad Explanations:

You see, according to MSDN, each LIST_ENTRY we get from the LDR space is actually a pointer to a struct of the type LDR_DATA_TABLE_ENTRY. This struct is defined as follows from MSDN.

Code:
typedef struct _LDR_DATA_TABLE_ENTRY {
    PVOID Reserved1[2];
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2[2];
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
    UNICODE_STRING FullDllName;
    BYTE Reserved4[8];
    PVOID Reserved5[3];
    union {
        ULONG CheckSum;
        PVOID Reserved6;
    };
    ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

So, there's a f*** of Reserved data in here.
Not to mention, the FIRST EIGHT BYTES of the struct are reserved.
I quite literally have NO WAY of knowing WHERE this LIST_ENTRY I got from the LDR points to.

I mean, LIST_ENTRY is basically just storing PVOIDs, so maybe it really is at the beginning of the struct.

So I tried that.
Casting the value of currPos to a void pointer, then to PLDR_DATA_TABLE_ENTRY.

I'll save you the trouble. It didn't work. Bad values everywhere.

Ideally, I wanted to print this for each assembly:
Code:
printf(
    "Path: %s, Base Address @ 0x%p, Entry Point @ 0x%p\n",
    pLdrEntry->FullDllName,
    pLdrEntry->DllBase,
    pLdrEntry->EntryPoint
);

There are problems with that too, but that's a basic idea of what I wanted to output.
So when I was getting undefined gibberish after the simple casting, I knew something was up.

By then I noticed that there's a LIST_ENTRY struct located in the LDR_ENTRY.
So I decided to take advantage of a different WinAPI macro to help out:

Code:
PLDR_DATA_TABLE_ENTRY pLdrEntry = CONTAINING_RECORD(
    currPos,
    LDR_DATA_TABLE_ENTRY,
    InMemoryOrderLinks
);

The CONTAINING_RECORD() macro takes three parameters in. It expands to weird pointer arithmetic BS, but the gist is as follows:

The first parameter is the pointer to the structure in question.
The second parameter is the struct definition that we want to try and cast to.
The third parameter is the name of the field in the struct (defined by second param) that we believe the first parameter is pointing to.

And using that data, CONTAINING_RECORD() will now offset the pointer accordingly so that the beginning/base of the struct (second param) is where the returned pointer is pointing to.

Now, if we run the printf() from earlier, well, you'll still get some issues.

You see, the first problem lies in the fact that FullDllName isn't a normal char* string as you'd expect a string to be. It's a UNICODE_STRING struct. So:
1. We can't print it using the %s format specifier for printf()
2. We need to get the text data from the struct.

So instead, we need to use a wide-char string specifier for unicode strings, and we also need to get the buffer of the string and not its other length/max-length properties.

But there's another issue.
Although MSDN defines an EntryPoint property of the struct for the LDR_DATA_TABLE_ENTRY, in the header files included with Windows/VisualStudio 2019, it's merged with Reserved3 which is also of type PVOID.

So instead of this...
Code:
[...]
    PVOID DllBase;
    PVOID EntryPoint;
    PVOID Reserved3;
[...]

We've got this:
Code:
[...]
    PVOID DllBase;
    PVOID Reserved3[2];
[...]

So, altogether, our new iterating/printing loop (th elast bit of our code) will look like this:

Code:
PLDR_DATA_TABLE_ENTRY pLdrEntry;
    for (int i = 0; i < moduleCount; ++i) {

        pLdrEntry = CONTAINING_RECORD(
            currPos,
            LDR_DATA_TABLE_ENTRY,
            InMemoryOrderLinks
        );

        printf(
            "Path: %ls, Base Address @ 0x%p, Entry Point @ 0x%p\n",
            pLdrEntry->FullDllName.Buffer,
            pLdrEntry->DllBase,
            pLdrEntry->Reserved3[0]
        );

        currPos = currPos->Flink;
    }

And we're done!

Let's finally run the code and see what we can find...



Build and Execute:

I wrote the code in Visual Studio 2019 using more or less default settings for everything.
I kept it all C-like, but I mean it still uses the MSVC compiler so whatever. Maybe a header in there uses C++ and I'm unaware.

I set it to Release settings, built for 64bit since I have a 64bit machine and didn't want SysWOW64 emulation. The result filesize was 12KB.

Here's the final code:
https://pastebin.com/33uqTh84

Here's the output:
[Image: DhsvDGS.png]

Forgive the blue, it's just default powershell.

But as you can see, all the memory addresses get printed out.
We now have the address of kernelbase.dll in memory, just as the question asked.

Now, one interesting thing to note is that if you run this over and over again, the PEB address changes, yeah, but the offsets for the loaded modules never changes. the kernel just loads them into those base addresses by default.

So you could find those offsets in memory by running your own process, to find the offsets of another process. Remember when I said OpenProcess() might run into permission errors? Now we can entirely avoid that by making your own process.

Let's take it a step further and why it might be important to note stuff like this:
Antivirus software tends to only scan for certain signatures, and make sure that whatever libraries and functions are being imported aren't too shady. well, if you're loading dynamically (and maybe getting some help from LD_PRELOAD), then you might get lower detection rates.

Anticheat software tries to make sure you aren't doing anything on the sidelines like this. Again, if you know where stuff is loaded in memory, you can dynamically load it ideally without getting detected.

Now, ASLR is tough, but not impossible to work around. Using some ROP techniques as outlined here, you could also abuse win32 functions for privilege escalation and shellcoding at your own will.

Print this item

  The Bug Reports Thread
Posted by: Darth-Apple - June 14th, 2020 at 4:35 PM - Forum: Community Related - Replies (29)

Hello all, 

In response to the recent removal of a lot of plugins, moving to a new server, among other things, there have been some issues that we are aware of with the forums. We're gonna start tackling these one by one over the next few weeks. We already know of a number of them: 

Todo:

  • Shoutbox is acting strangely
  • Mispellings in Core T7 (This theme is no longer maintained and is years old, but we will start resolving some old issues and fixing some things in the coming weeks).
  • Registration has issues
  • PMs and Posts randomly refuse to be sent with "error" page 
  • The built-in image uploader is gone, looking into alternatives 
  • Improve the mobile theme and fix the thread display (reporeted by s3_gunzel)
Fixed:
  • Profiles not working on Core T7 and MyBB Default (resolved)
  • "Abous us" on header dropdown (Thank you @Thomas and @Lain )
This thread will serve as the official bug reports thread. Please report any additional bugs, issues, or glitches here, and we will look into resolving them as well! 

-Admins

Print this item

  Ask Kyng
Posted by: Kyng - June 14th, 2020 at 3:41 PM - Forum: AMA Zone - Replies (9)

Go ahead and ask me questions Smile !

Print this item

  MyBB 1.9 ?
Posted by: tc4me - June 14th, 2020 at 5:36 AM - Forum: MyBB Related - Replies (31)

I think the development of MyBB1.9 has reached a point where the paths will separate. Either the many commits manage to concentrate on one or if it continues as before, 1.9 will be an unfinished one for years to come.
We read a lot in forums, many want to leave the communits again, because too many cooks spoil the broth

Print this item

  Tattoo and/or Piercing ?
Posted by: tc4me - June 13th, 2020 at 4:32 PM - Forum: The Others - Replies (5)

What do you think of tattoos and piercing? Are you tattooed or pierced?

lg Tc4me

Print this item

  Ben loves flowers and of course wind turbines :-)
Posted by: tc4me - June 12th, 2020 at 8:34 PM - Forum: Photography - Replies (5)

A nice early evening ... Ben loves flowers and of course wind turbines :-)



Attached Files Thumbnail(s)
               
Print this item

  Makestation IRC Channel
Posted by: Thomas - June 12th, 2020 at 2:23 AM - Forum: General Discussion - Replies (13)

Join me in ##makestation (yes that's two #) on irc.freenode.net! Let's see if we can make this a thing.

Print this item

  Ben today at the electricity pylon
Posted by: tc4me - June 11th, 2020 at 2:59 PM - Forum: Photography - Replies (6)

   

   

   

Blush FUN Day

Print this item

  spork985
Posted by: Thomas - June 11th, 2020 at 2:14 AM - Forum: General Discussion - Replies (7)

I sure miss that guy Sad Come back spork!

Print this item

  Social justice?
Posted by: tc4me - June 9th, 2020 at 10:22 AM - Forum: Current Events - Replies (4)

Hy guys, hope Google translates that correctly, it's about my son Ben Jay, he's 70% disabled, he can't ride a tricycle or ride a bike, that's why we applied for a disabled tricycle through his health insurance. Costs 4500 euros also in dollars. On the grounds that he doesn't have to ride a bike, the application was rejected. and that I call VIOLATION OF EQUALITY! Because of the alleged police attacks in the USA, 50,000 people go to Austria to demonstrate who is going on the street for my child? my child is not a criminal or ex criminal, my son is 6 years old and would like to ride a tricycle or bike like other children.

I am really angry,

Print this item


Dark/Light Theme Selector

Contact Us | Makestation | Return to Top | Lite (Archive) Mode | RSS Syndication 
Proudly powered by MyBB 1.8, © 2002-2024
Forum design by Makestation Team © 2013-2024