With the theorem packages you would normally use \qed as described in this answer. Without those you use the commands below depending on if you want the filled square or empty.
When the line is too full for a square it will be placed on the new line, but since \hfill only works when there are characters on the line, the square will be placed left. You can precede \hfill by \null\nobreak to fix this. (\null inserts and empty \hbox and \nobreak is necessary to prevent this box from simply being placed on the previous line, where it'd be ineffective)

\documentclass[a4paper]{article} \usepackage{amssymb} %% <- for \square and \blacksuare \newcommand*{\QEDA}{\null\nobreak\hfill\ensuremath{\blacksquare}}% \newcommand*{\QEDB}{\null\nobreak\hfill\ensuremath{\square}}% \begin{document} Lorem ipsum \QEDA Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod!?! \QEDB \end{document}
Note:
The \qed command from amsthm employs a few additional tricks. A fully featured version of the above commands (with an optional argument for the symbol to use) would read
\newcommand*{\QED}[1][$\square$]{% \leavevmode\unskip\penalty9999 \hbox{}\nobreak\hfill \quad\hbox{#1}% }
(\leavevmode makes the command usable outside a paragraph (don't do this, though) \unskip removes a preceding space if there is one, \hbox{} is the same as \null, \penalty9999 ensures that TeX will try its utmost to squeeze the symbol into the same line as the preceding text and \quad separates the symbol from the text by a bit.)